Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api-kit): add ordering props to getPendingTransactions #1011

Merged
merged 1 commit into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 58 additions & 2 deletions packages/api-kit/src/SafeApiKit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
ListOptions,
ModulesResponse,
OwnerResponse,
PendingTransactionsOptions,
ProposeTransactionProps,
SafeCreationInfoResponse,
SafeDelegateListResponse,
Expand Down Expand Up @@ -120,7 +121,7 @@
* @throws "Not Found"
* @throws "Ensure this field has at least 1 hexadecimal chars (not counting 0x)."
*/
async decodeData(data: string): Promise<any> {

Check warning on line 124 in packages/api-kit/src/SafeApiKit.ts

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type
if (data === '') {
throw new Error('Invalid data')
}
Expand Down Expand Up @@ -330,7 +331,7 @@
const { address: delegator } = this.#getEip3770Address(delegatorAddress)
const signature = await signDelegate(signer, delegate, this.#chainId)

const body: any = {

Check warning on line 334 in packages/api-kit/src/SafeApiKit.ts

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type
safe: safeAddress ? this.#getEip3770Address(safeAddress).address : null,
delegate,
delegator,
Expand Down Expand Up @@ -528,7 +529,7 @@
* Returns the list of multi-signature transactions that are waiting for the confirmation of the Safe owners.
*
* @param safeAddress - The Safe address
* @param currentNonce - Current nonce of the Safe
* @param currentNonce - Deprecated, use inside object property: Current nonce of the Safe.
* @returns The list of transactions waiting for the confirmation of the Safe owners
* @throws "Invalid Safe address"
* @throws "Invalid data"
Expand All @@ -537,15 +538,70 @@
async getPendingTransactions(
safeAddress: string,
currentNonce?: number
): Promise<SafeMultisigTransactionListResponse>
/**
* Returns the list of multi-signature transactions that are waiting for the confirmation of the Safe owners.
*
* @param safeAddress - The Safe address
* @param {PendingTransactionsOptions} options The options to filter the list of transactions
* @returns The list of transactions waiting for the confirmation of the Safe owners
* @throws "Invalid Safe address"
* @throws "Invalid data"
* @throws "Invalid ethereum address"
*/
async getPendingTransactions(
safeAddress: string,
{ currentNonce, hasConfirmations, ordering, limit, offset }: PendingTransactionsOptions
): Promise<SafeMultisigTransactionListResponse>
async getPendingTransactions(
safeAddress: string,
propsOrCurrentNonce: PendingTransactionsOptions | number = {}
): Promise<SafeMultisigTransactionListResponse> {
if (safeAddress === '') {
throw new Error('Invalid Safe address')
}

// TODO: Remove @deprecated migration code
let currentNonce: number | undefined
let hasConfirmations: boolean | undefined
let ordering: string | undefined
let limit: number | undefined
let offset: number | undefined
if (typeof propsOrCurrentNonce === 'object') {
;({ currentNonce, hasConfirmations, ordering, limit, offset } = propsOrCurrentNonce)
} else {
console.warn(
'Deprecated: Use `currentNonce` inside an object instead. See `PendingTransactionsOptions`.'
)
currentNonce = propsOrCurrentNonce
}
// END of @deprecated migration code

const { address } = this.#getEip3770Address(safeAddress)
const nonce = currentNonce ? currentNonce : (await this.getSafeInfo(address)).nonce

const url = new URL(
`${this.#txServiceBaseUrl}/v1/safes/${address}/multisig-transactions/?executed=false&nonce__gte=${nonce}`
)

if (hasConfirmations) {
url.searchParams.set('has_confirmations', hasConfirmations.toString())
}

if (ordering) {
url.searchParams.set('ordering', ordering)
}

if (limit != null) {
url.searchParams.set('limit', limit.toString())
}

if (offset != null) {
url.searchParams.set('offset', offset.toString())
}

return sendRequest({
url: `${this.#txServiceBaseUrl}/v1/safes/${address}/multisig-transactions/?executed=false&nonce__gte=${nonce}`,
url: url.toString(),
method: HttpMethod.Get
})
}
Expand Down
7 changes: 7 additions & 0 deletions packages/api-kit/src/types/safeTransactionServiceTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@ export type ProposeTransactionProps = {
origin?: string
}

export type PendingTransactionsOptions = {
currentNonce?: number
hasConfirmations?: boolean
/** Which field to use when ordering the results. It can be: `nonce`, `created`, `modified` (default: `-created`) */
ordering?: string
} & ListOptions

export type SafeMultisigTransactionListResponse = ListResponse<SafeMultisigTransactionResponse>

export type TransferResponse = {
Expand Down
22 changes: 22 additions & 0 deletions packages/api-kit/tests/e2e/getPendingTransactions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,26 @@ describe('getPendingTransactions', () => {
chai.expect(transactionList.count).to.be.equal(10)
chai.expect(transactionList.results.length).to.be.equal(10)
})

it('should return a maximum of 2 transactions with limit = 2', async () => {
const safeAddress = '0xCa2f5A815b642c79FC530B60BC15Aee4eF6252b3' // Safe with pending transaction
const transactionList = await safeApiKit.getPendingTransactions(safeAddress, {
limit: 2
})

chai.expect(transactionList).to.have.property('count').greaterThan(1)
chai.expect(transactionList).to.have.property('results').to.be.an('array')
chai.expect(transactionList.results.length).to.be.equal(2)
})

it('should return all pending transactions excluding the first one with offset = 1', async () => {
const safeAddress = '0xCa2f5A815b642c79FC530B60BC15Aee4eF6252b3' // Safe with pending transaction
const transactionList = await safeApiKit.getPendingTransactions(safeAddress, {
offset: 1
})

chai.expect(transactionList).to.have.property('count').greaterThan(1)
chai.expect(transactionList).to.have.property('results').to.be.an('array')
chai.expect(transactionList.results.length).to.be.lessThanOrEqual(transactionList.count - 1)
})
})
4 changes: 2 additions & 2 deletions packages/api-kit/tests/endpoint/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ describe('Endpoint tests', () => {
it('getPendingTransactions', async () => {
const currentNonce = 1
await chai
.expect(safeApiKit.getPendingTransactions(safeAddress, currentNonce))
.expect(safeApiKit.getPendingTransactions(safeAddress, { currentNonce }))
.to.be.eventually.deep.equals({ data: { success: true } })
chai.expect(fetchData).to.have.been.calledWith({
url: `${txServiceBaseUrl}/v1/safes/${safeAddress}/multisig-transactions/?executed=false&nonce__gte=${currentNonce}`,
Expand All @@ -523,7 +523,7 @@ describe('Endpoint tests', () => {
it('getPendingTransactions EIP-3770', async () => {
const currentNonce = 1
await chai
.expect(safeApiKit.getPendingTransactions(eip3770SafeAddress, currentNonce))
.expect(safeApiKit.getPendingTransactions(eip3770SafeAddress, { currentNonce }))
.to.be.eventually.deep.equals({ data: { success: true } })
chai.expect(fetchData).to.have.been.calledWith({
url: `${txServiceBaseUrl}/v1/safes/${safeAddress}/multisig-transactions/?executed=false&nonce__gte=${currentNonce}`,
Expand Down
1 change: 0 additions & 1 deletion packages/protocol-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
],
"homepage": "https://github.com/safe-global/safe-core-sdk#readme",
"devDependencies": {
"@safe-global/safe-passkey": "0.2.0-alpha.1",
"@safe-global/testing-kit": "^0.1.0",
"@types/chai": "^4.3.19",
"@types/chai-as-promised": "^7.1.8",
Expand Down
1 change: 1 addition & 0 deletions packages/testing-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@nomicfoundation/hardhat-viem": "^2.0.4",
"@openzeppelin/contracts": "^2.5.1",
"@safe-global/safe-contracts-v1.4.1": "npm:@safe-global/[email protected]",
"@safe-global/safe-passkey": "0.2.0-alpha.1",
"@safe-global/types-kit": "^1.0.0",
"@types/semver": "^7.5.8",
"hardhat": "^2.19.3",
Expand Down
Loading