Skip to content

Commit

Permalink
Merge pull request safe-global#119 from ioloie/feature/all-transactions
Browse files Browse the repository at this point in the history
Add getAllTransactions endpoint to Safe Service Client
  • Loading branch information
germartinez authored Dec 21, 2021
2 parents e37d7f4 + c2c8a8d commit 678b0aa
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 2 deletions.
20 changes: 20 additions & 0 deletions packages/safe-service-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,26 @@ const pendingTxs: SafeMultisigTransactionListResponse = await safeService.getPen
)
```

### getAllTransactions

Returns a list of transactions for a Safe. The list has different structures depending on the transaction type.

```js
const allTxs: SafeMultisigTransactionListResponse = await safeService.getAllTransactions(safeAddress)
```

```js
const allTxsOptions: AllTransactionsOptions = {
executed,
queued,
trusted
}
const allTxs: SafeMultisigTransactionListResponse = await safeService.getAllTransactions(
safeAddress,
allTxsOptions
)
```

### getNextNonce

Returns the right nonce to propose a new transaction right after the last pending transaction.
Expand Down
2 changes: 1 addition & 1 deletion packages/safe-service-client/e2e/getNextNonce.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ describe('getNextNonce', () => {
const nextNonce = await serviceSdk.getNextNonce(safeAddress)
chai.expect(nextNonce).to.be.equal(0)
})
})
})
41 changes: 40 additions & 1 deletion packages/safe-service-client/src/SafeServiceClient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Signer } from '@ethersproject/abstract-signer'
import SafeTransactionService from './SafeTransactionService'
import {
AllTransactionsListResponse,
AllTransactionsOptions,
MasterCopyResponse,
OwnerResponse,
ProposeTransactionProps,
Expand Down Expand Up @@ -212,7 +214,12 @@ class SafeServiceClient implements SafeTransactionService {
* @throws "Safe=<safe_address> does not exist or it's still not indexed"
* @throws "Signing owner is not an owner of the Safe"
*/
async addSafeDelegate({ safe, delegate, label, signer }: SafeDelegateConfig): Promise<SafeDelegate> {
async addSafeDelegate({
safe,
delegate,
label,
signer
}: SafeDelegateConfig): Promise<SafeDelegate> {
if (safe === '') {
throw new Error('Invalid Safe address')
}
Expand Down Expand Up @@ -452,6 +459,38 @@ class SafeServiceClient implements SafeTransactionService {
})
}

/**
* Returns a list of transactions for a Safe. The list has different structures depending on the transaction type
*
* @param safeAddress - The Safe address
* @returns The list of transactions waiting for the confirmation of the Safe owners
* @throws "Invalid Safe address"
* @throws "Checksum address validation failed"
*/
async getAllTransactions(
safeAddress: string,
options?: AllTransactionsOptions
): Promise<AllTransactionsListResponse> {
if (safeAddress === '') {
throw new Error('Invalid Safe address')
}
const url = new URL(`${this.#txServiceBaseUrl}/safes/${safeAddress}/all-transactions/`)

const trusted = options?.trusted?.toString() || 'true'
url.searchParams.set('trusted', trusted)

const queued = options?.queued?.toString() || 'true'
url.searchParams.set('queued', queued)

const executed = options?.executed?.toString() || 'false'
url.searchParams.set('executed', executed)

return sendRequest({
url: url.toString(),
method: HttpMethod.Get
})
}

/**
* Returns the right nonce to propose a new transaction after the last pending transaction.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,48 @@ export type TokenInfoListResponse = {
readonly previous?: string
readonly results: TokenInfoListResponse[]
}

export type TransferWithTokenInfoResponse = TransferResponse & {
readonly tokenInfo: TokenInfoResponse
}

export type SafeModuleTransactionWithTransfersResponse = SafeModuleTransaction & {
readonly txType?: 'MODULE_TRANSACTION'
readonly transfers: TransferWithTokenInfoResponse[]
}

export type SafeMultisigTransactionWithTransfersResponse = SafeMultisigTransactionResponse & {
readonly txType?: 'MULTISIG_TRANSACTION'
readonly transfers: TransferWithTokenInfoResponse[]
}

export type EthereumTxResponse = {
readonly executionDate: string
readonly to: string
readonly data: string
readonly txHash: string
readonly blockNumber?: number
readonly from: string
}

export type EthereumTxWithTransfersResponse = EthereumTxResponse & {
readonly txType?: 'ETHEREUM_TRANSACTION'
readonly transfers: TransferWithTokenInfoResponse[]
}

export type AllTransactionsOptions = {
executed?: boolean
queued?: boolean
trusted?: boolean
}

export type AllTransactionsListResponse = {
readonly count: number
readonly next?: string
readonly previous?: string
readonly results: Array<
| SafeModuleTransactionWithTransfersResponse
| SafeMultisigTransactionWithTransfersResponse
| EthereumTxWithTransfersResponse
>
}
12 changes: 12 additions & 0 deletions packages/safe-service-client/tests/endpoint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,18 @@ describe('Endpoint tests', () => {
})
})

it('getAllTransactions', async () => {
await chai
.expect(serviceSdk.getAllTransactions(safeAddress))
.to.be.eventually.deep.equals({ data: { success: true } })
chai.expect(fetchData).to.have.been.calledWith({
url: `${getTxServiceBaseUrl(
txServiceBaseUrl
)}/safes/${safeAddress}/all-transactions/?trusted=true&queued=true&executed=false`,
method: 'get'
})
})

it('getBalances', async () => {
await chai
.expect(serviceSdk.getBalances(safeAddress))
Expand Down

0 comments on commit 678b0aa

Please sign in to comment.