From a157f360b487e6873139b43e233146687de43601 Mon Sep 17 00:00:00 2001 From: Daniel <25051234+dasanra@users.noreply.github.com> Date: Thu, 16 Jan 2025 17:06:13 +0100 Subject: [PATCH 1/3] fix(api-kit): add missing properties to types --- packages/api-kit/src/SafeApiKit.ts | 8 ++++ .../src/types/safeTransactionServiceTypes.ts | 48 ++++++++----------- .../tests/e2e/addMessageSignature.test.ts | 3 +- .../api-kit/tests/e2e/addSafeDelegate.test.ts | 13 ++--- .../tests/e2e/getIncomingTransactions.test.ts | 37 ++++++++++++-- packages/api-kit/tests/e2e/getMessage.test.ts | 3 +- .../api-kit/tests/e2e/getMessages.test.ts | 3 +- .../api-kit/tests/e2e/getNextNonce.test.ts | 10 ++-- .../tests/e2e/getSafeDelegates.test.ts | 4 +- .../api-kit/tests/e2e/getSafeInfo.test.ts | 31 ++++++++++-- .../tests/e2e/getSafesByModule.test.ts | 6 +-- .../api-kit/tests/e2e/getServiceInfo.test.ts | 6 +-- packages/api-kit/tests/helpers/safe.ts | 15 ++++++ packages/types-kit/src/types.ts | 18 ++++++- 14 files changed, 146 insertions(+), 59 deletions(-) create mode 100644 packages/api-kit/tests/helpers/safe.ts diff --git a/packages/api-kit/src/SafeApiKit.ts b/packages/api-kit/src/SafeApiKit.ts index 2067ac103..004315501 100644 --- a/packages/api-kit/src/SafeApiKit.ts +++ b/packages/api-kit/src/SafeApiKit.ts @@ -258,6 +258,14 @@ class SafeApiKit { return sendRequest({ url: `${this.#txServiceBaseUrl}/v1/safes/${address}/`, method: HttpMethod.Get + }).then((response: any) => { + // FIXME remove when service returns the singleton property + if (!response?.singleton) { + const { masterCopy, ...rest } = response + return { ...rest, singleton: masterCopy } as SafeInfoResponse + } + + return response as SafeInfoResponse }) } diff --git a/packages/api-kit/src/types/safeTransactionServiceTypes.ts b/packages/api-kit/src/types/safeTransactionServiceTypes.ts index 6a044b7ad..a1418aa74 100644 --- a/packages/api-kit/src/types/safeTransactionServiceTypes.ts +++ b/packages/api-kit/src/types/safeTransactionServiceTypes.ts @@ -134,20 +134,6 @@ export type PendingTransactionsOptions = { export type SafeMultisigTransactionListResponse = ListResponse -export type TransferResponse = { - readonly type?: string - readonly executionDate: string - readonly blockNumber: number - readonly transactionHash: string - readonly to: string - readonly value: string - readonly tokenId: string - readonly tokenAddress?: string - readonly from: string -} - -export type TransferListResponse = ListResponse - export type SafeModuleTransaction = { readonly created?: string readonly executionDate: string @@ -165,36 +151,42 @@ export type SafeModuleTransaction = { export type SafeModuleTransactionListResponse = ListResponse -export type Erc20Info = { - readonly name: string - readonly symbol: string - readonly decimals: number - readonly logoUri: string +export type TransferResponse = { + readonly type: string + readonly executionDate: string + readonly blockNumber: number + readonly transactionHash: string + readonly to: string + readonly value?: string + readonly tokenId?: string + readonly tokenAddress?: string + readonly transferId: string + readonly tokenInfo?: TokenInfoResponse + readonly from: string } +export type TransferListResponse = ListResponse + export type TokenInfoResponse = { - readonly type?: string + readonly type: string readonly address: string readonly name: string readonly symbol: string - readonly decimals: number + readonly decimals?: number readonly logoUri?: string + readonly trusted: boolean } export type TokenInfoListResponse = ListResponse -export type TransferWithTokenInfoResponse = TransferResponse & { - readonly tokenInfo: TokenInfoResponse -} - export type SafeModuleTransactionWithTransfersResponse = SafeModuleTransaction & { readonly txType?: 'MODULE_TRANSACTION' - readonly transfers: TransferWithTokenInfoResponse[] + readonly transfers: TransferResponse[] } export type SafeMultisigTransactionWithTransfersResponse = SafeMultisigTransactionResponse & { readonly txType?: 'MULTISIG_TRANSACTION' - readonly transfers: TransferWithTokenInfoResponse[] + readonly transfers: TransferResponse[] } export type EthereumTxResponse = { @@ -208,7 +200,7 @@ export type EthereumTxResponse = { export type EthereumTxWithTransfersResponse = EthereumTxResponse & { readonly txType?: 'ETHEREUM_TRANSACTION' - readonly transfers: TransferWithTokenInfoResponse[] + readonly transfers: TransferResponse[] } export type AllTransactionsOptions = { diff --git a/packages/api-kit/tests/e2e/addMessageSignature.test.ts b/packages/api-kit/tests/e2e/addMessageSignature.test.ts index 62255cecb..86ee5239f 100644 --- a/packages/api-kit/tests/e2e/addMessageSignature.test.ts +++ b/packages/api-kit/tests/e2e/addMessageSignature.test.ts @@ -10,6 +10,7 @@ import SafeApiKit from '@safe-global/api-kit/index' import chai from 'chai' import chaiAsPromised from 'chai-as-promised' import { getKits } from '../utils/setupKits' +import { API_TESTING_SAFE } from '../helpers/safe' chai.use(chaiAsPromised) @@ -18,7 +19,7 @@ const PRIVATE_KEY_2 = '0xb88ad5789871315d0dab6fc5961d6714f24f35a6393f13a6f426dfe let safeApiKit: SafeApiKit let protocolKit: Safe -const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' +const safeAddress = API_TESTING_SAFE.address const signerSafeAddress = '0xDa8dd250065F19f7A29564396D7F13230b9fC5A3' const generateRandomUUID = (): string => { diff --git a/packages/api-kit/tests/e2e/addSafeDelegate.test.ts b/packages/api-kit/tests/e2e/addSafeDelegate.test.ts index f6dd45b7f..957625c9c 100644 --- a/packages/api-kit/tests/e2e/addSafeDelegate.test.ts +++ b/packages/api-kit/tests/e2e/addSafeDelegate.test.ts @@ -6,6 +6,7 @@ import chai from 'chai' import chaiAsPromised from 'chai-as-promised' import config from '../utils/config' import { getApiKit } from '../utils/setupKits' +import { API_TESTING_SAFE } from '../helpers/safe' chai.use(chaiAsPromised) @@ -68,7 +69,7 @@ describe('addSafeDelegate', () => { }) it('should fail if Safe address is not checksummed', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78'.toLowerCase() + const safeAddress = API_TESTING_SAFE.address.toLowerCase() const delegateAddress = '0x9cCBDE03eDd71074ea9c49e413FA9CDfF16D263B' const delegateConfig: AddSafeDelegateProps = { safeAddress, @@ -83,7 +84,7 @@ describe('addSafeDelegate', () => { }) it('should fail if Safe delegate address is not checksummed', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' + const safeAddress = API_TESTING_SAFE.address const delegateAddress = '0x9cCBDE03eDd71074ea9c49e413FA9CDfF16D263B'.toLowerCase() const delegateConfig: AddSafeDelegateProps = { safeAddress, @@ -98,7 +99,7 @@ describe('addSafeDelegate', () => { }) it('should fail if Safe delegator address is not checksummed', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' + const safeAddress = API_TESTING_SAFE.address const delegateAddress = '0x9cCBDE03eDd71074ea9c49e413FA9CDfF16D263B' const delegatorAddressLowerCase = delegatorAddress.toLowerCase() const delegateConfig: AddSafeDelegateProps = { @@ -129,7 +130,7 @@ describe('addSafeDelegate', () => { }) it('should fail if the signer is not an owner of the Safe', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' + const safeAddress = API_TESTING_SAFE.address const delegateAddress = '0x9cCBDE03eDd71074ea9c49e413FA9CDfF16D263B' const nonOwnerSigner = createWalletClient({ chain: sepolia, @@ -152,7 +153,7 @@ describe('addSafeDelegate', () => { }) it('should add a new delegate', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' + const safeAddress = API_TESTING_SAFE.address const delegateAddress = '0x9cCBDE03eDd71074ea9c49e413FA9CDfF16D263B' const delegateConfig: AddSafeDelegateProps = { safeAddress, @@ -201,7 +202,7 @@ describe('addSafeDelegate', () => { }) it('should add a new delegate EIP-3770', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' + const safeAddress = API_TESTING_SAFE.address const eip3770SafeAddress = `${config.EIP_3770_PREFIX}:${safeAddress}` const delegateAddress = '0x9cCBDE03eDd71074ea9c49e413FA9CDfF16D263B' const eip3770DelegateAddress = `${config.EIP_3770_PREFIX}:${delegateAddress}` diff --git a/packages/api-kit/tests/e2e/getIncomingTransactions.test.ts b/packages/api-kit/tests/e2e/getIncomingTransactions.test.ts index 85c9b1ef8..dd0cf71b8 100644 --- a/packages/api-kit/tests/e2e/getIncomingTransactions.test.ts +++ b/packages/api-kit/tests/e2e/getIncomingTransactions.test.ts @@ -3,6 +3,7 @@ import chaiAsPromised from 'chai-as-promised' import SafeApiKit from '@safe-global/api-kit/index' import config from '../utils/config' import { getApiKit } from '../utils/setupKits' +import { API_TESTING_SAFE } from '../helpers/safe' chai.use(chaiAsPromised) @@ -21,7 +22,7 @@ describe('getIncomingTransactions', () => { }) it('should fail if Safe address is not checksummed', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78'.toLowerCase() + const safeAddress = API_TESTING_SAFE.address.toLowerCase() await chai .expect(safeApiKit.getIncomingTransactions(safeAddress)) .to.be.rejectedWith('Checksum address validation failed') @@ -35,23 +36,53 @@ describe('getIncomingTransactions', () => { }) it('should return the list of incoming transactions', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' // Safe with incoming transactions + const safeAddress = API_TESTING_SAFE.address // Safe with incoming transactions const transferListResponse = await safeApiKit.getIncomingTransactions(safeAddress) chai.expect(transferListResponse.count).to.be.equal(6) chai.expect(transferListResponse.results.length).to.be.equal(6) transferListResponse.results.map((transaction) => { chai.expect(transaction.to).to.be.equal(safeAddress) + chai.expect(transaction).to.have.property('from').to.be.a('string') + chai.expect(transaction).to.have.property('executionDate').to.be.a('string') + chai.expect(transaction).to.have.property('blockNumber').to.be.a('number') + chai.expect(transaction).to.have.property('transactionHash').to.be.a('string') + chai.expect(transaction).to.have.property('transferId').to.be.a('string') + if (transaction.type === 'ETHER_TRANSFER') { + chai.expect(transaction.value).to.not.be.null + chai.expect(transaction.tokenId).to.be.null + chai.expect(transaction.tokenAddress).to.be.null + chai.expect(transaction.tokenInfo).to.be.null + } else if (transaction.type === 'ERC20_TRANSFER') { + chai.expect(transaction.tokenId).to.not.be.null + chai.expect(transaction.tokenAddress).to.not.be.null + chai.expect(transaction.tokenInfo).to.not.be.null + } }) }) it('should return the list of incoming transactions EIP-3770', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' // Safe with incoming transactions + const safeAddress = API_TESTING_SAFE.address // Safe with incoming transactions const eip3770SafeAddress = `${config.EIP_3770_PREFIX}:${safeAddress}` const transferListResponse = await safeApiKit.getIncomingTransactions(eip3770SafeAddress) chai.expect(transferListResponse.count).to.be.equal(6) chai.expect(transferListResponse.results.length).to.be.equal(6) transferListResponse.results.map((transaction) => { chai.expect(transaction.to).to.be.equal(safeAddress) + chai.expect(transaction).to.have.property('from').to.be.a('string') + chai.expect(transaction).to.have.property('executionDate').to.be.a('string') + chai.expect(transaction).to.have.property('blockNumber').to.be.a('number') + chai.expect(transaction).to.have.property('transactionHash').to.be.a('string') + chai.expect(transaction).to.have.property('transferId').to.be.a('string') + if (transaction.type === 'ETHER_TRANSFER') { + chai.expect(transaction.value).to.not.be.null + chai.expect(transaction.tokenId).to.be.null + chai.expect(transaction.tokenAddress).to.be.null + chai.expect(transaction.tokenInfo).to.be.null + } else if (transaction.type === 'ERC20_TRANSFER') { + chai.expect(transaction.tokenId).to.not.be.null + chai.expect(transaction.tokenAddress).to.not.be.null + chai.expect(transaction.tokenInfo).to.not.be.null + } }) }) }) diff --git a/packages/api-kit/tests/e2e/getMessage.test.ts b/packages/api-kit/tests/e2e/getMessage.test.ts index 52574e3c6..498cecfad 100644 --- a/packages/api-kit/tests/e2e/getMessage.test.ts +++ b/packages/api-kit/tests/e2e/getMessage.test.ts @@ -2,11 +2,12 @@ import SafeApiKit from '@safe-global/api-kit/index' import chai from 'chai' import chaiAsPromised from 'chai-as-promised' import { getApiKit } from '../utils/setupKits' +import { API_TESTING_SAFE } from '../helpers/safe' chai.use(chaiAsPromised) let safeApiKit: SafeApiKit -const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' +const safeAddress = API_TESTING_SAFE.address describe('getMessage', () => { before(async () => { diff --git a/packages/api-kit/tests/e2e/getMessages.test.ts b/packages/api-kit/tests/e2e/getMessages.test.ts index 07507c7cc..0baafe697 100644 --- a/packages/api-kit/tests/e2e/getMessages.test.ts +++ b/packages/api-kit/tests/e2e/getMessages.test.ts @@ -2,11 +2,12 @@ import SafeApiKit from '@safe-global/api-kit/index' import chai from 'chai' import chaiAsPromised from 'chai-as-promised' import { getApiKit } from '../utils/setupKits' +import { API_TESTING_SAFE } from '../helpers/safe' chai.use(chaiAsPromised) let safeApiKit: SafeApiKit -const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' +const safeAddress = API_TESTING_SAFE.address describe('getMessages', () => { before(async () => { diff --git a/packages/api-kit/tests/e2e/getNextNonce.test.ts b/packages/api-kit/tests/e2e/getNextNonce.test.ts index 029ac5af3..297e2dec1 100644 --- a/packages/api-kit/tests/e2e/getNextNonce.test.ts +++ b/packages/api-kit/tests/e2e/getNextNonce.test.ts @@ -3,6 +3,8 @@ import chaiAsPromised from 'chai-as-promised' import SafeApiKit from '@safe-global/api-kit/index' import config from '../utils/config' import { getApiKit } from '../utils/setupKits' +import { API_TESTING_SAFE } from '../helpers/safe' + chai.use(chaiAsPromised) let safeApiKit: SafeApiKit @@ -20,16 +22,16 @@ describe('getNextNonce', () => { }) it('should return the next Safe nonce when there are pending transactions', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' + const safeAddress = API_TESTING_SAFE.address const nextNonce = await safeApiKit.getNextNonce(safeAddress) - chai.expect(nextNonce).to.be.equal(13) + chai.expect(nextNonce).to.be.equal(API_TESTING_SAFE.nonce + 2) }) it('should return the next Safe nonce when there are pending transactions EIP-3770', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' + const safeAddress = API_TESTING_SAFE.address const eip3770SafeAddress = `${config.EIP_3770_PREFIX}:${safeAddress}` const nextNonce = await safeApiKit.getNextNonce(eip3770SafeAddress) - chai.expect(nextNonce).to.be.equal(13) + chai.expect(nextNonce).to.be.equal(API_TESTING_SAFE.nonce + 2) }) it('should return the next Safe nonce when there are no pending transactions', async () => { diff --git a/packages/api-kit/tests/e2e/getSafeDelegates.test.ts b/packages/api-kit/tests/e2e/getSafeDelegates.test.ts index b8261f3c0..5c541c979 100644 --- a/packages/api-kit/tests/e2e/getSafeDelegates.test.ts +++ b/packages/api-kit/tests/e2e/getSafeDelegates.test.ts @@ -9,6 +9,7 @@ import chai from 'chai' import chaiAsPromised from 'chai-as-promised' import config from '../utils/config' import { getApiKit } from '../utils/setupKits' +import { API_TESTING_SAFE } from '../helpers/safe' chai.use(chaiAsPromised) @@ -19,7 +20,7 @@ let signer: DeleteSafeDelegateProps['signer'] let delegatorAddress: Address describe('getSafeDelegates', () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' + const safeAddress = API_TESTING_SAFE.address before(() => { safeApiKit = getApiKit('https://safe-transaction-sepolia.staging.5afe.dev/api') @@ -127,7 +128,6 @@ describe('getSafeDelegates', () => { }) it('should return an array of delegates EIP-3770', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' const eip3770SafeAddress = `${config.EIP_3770_PREFIX}:${safeAddress}` const delegateConfig1: DeleteSafeDelegateProps = { delegateAddress: `${config.EIP_3770_PREFIX}:0x9cCBDE03eDd71074ea9c49e413FA9CDfF16D263B`, diff --git a/packages/api-kit/tests/e2e/getSafeInfo.test.ts b/packages/api-kit/tests/e2e/getSafeInfo.test.ts index a6621ef3b..49069a5f7 100644 --- a/packages/api-kit/tests/e2e/getSafeInfo.test.ts +++ b/packages/api-kit/tests/e2e/getSafeInfo.test.ts @@ -3,6 +3,7 @@ import chai from 'chai' import chaiAsPromised from 'chai-as-promised' import config from '../utils/config' import { getApiKit } from '../utils/setupKits' +import { API_TESTING_SAFE } from '../helpers/safe' chai.use(chaiAsPromised) @@ -21,26 +22,46 @@ describe('getSafeInfo', () => { }) it('should fail if Safe address is not checksummed', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78'.toLowerCase() + const safeAddress = API_TESTING_SAFE.address.toLowerCase() await chai .expect(safeApiKit.getSafeInfo(safeAddress)) .to.be.rejectedWith('Checksum address validation failed') }) it('should return the Safe info if the address is correct', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' + const safeAddress = API_TESTING_SAFE.address const safeInfoResponse = await safeApiKit.getSafeInfo(safeAddress) chai.expect(safeInfoResponse.address).to.be.equal(safeAddress) chai.expect(safeInfoResponse.nonce).to.be.a('number') - chai.expect(safeInfoResponse.threshold).to.be.a('number') + chai.expect(safeInfoResponse.threshold).to.be.equal(API_TESTING_SAFE.threshold) + chai.expect(safeInfoResponse).to.have.property('owners').to.be.an('array') + chai.expect(safeInfoResponse).to.have.property('modules').to.be.an('array') + chai.expect(safeInfoResponse.fallbackHandler).to.eq(API_TESTING_SAFE.fallbackHandler) + chai.expect(safeInfoResponse.guard).to.eq(API_TESTING_SAFE.guard) + chai.expect(safeInfoResponse.version).to.eq(API_TESTING_SAFE.version) + chai.expect(safeInfoResponse).to.have.property('singleton').to.eq(API_TESTING_SAFE.singleton) + // FIXME currently the service returns masterCopy and we replace it by singleton on SafeApiKit. + // To avoid the breaking change they will return both propertys for a while, when this happens we can remove the hack at SafApiKit. + // The test will fail at that moment. + chai.expect(safeInfoResponse).not.to.have.property('masterCopy') }) it('should return the Safe info if EIP-3770 address is correct', async () => { - const safeAddress = '0xF8ef84392f7542576F6b9d1b140334144930Ac78' + const safeAddress = API_TESTING_SAFE.address const eip3770SafeAddress = `${config.EIP_3770_PREFIX}:${safeAddress}` const safeInfoResponse = await safeApiKit.getSafeInfo(eip3770SafeAddress) chai.expect(safeInfoResponse.address).to.be.equal(safeAddress) chai.expect(safeInfoResponse.nonce).to.be.a('number') - chai.expect(safeInfoResponse.threshold).to.be.a('number') + chai.expect(safeInfoResponse.threshold).to.be.equal(API_TESTING_SAFE.threshold) + chai.expect(safeInfoResponse).to.have.property('owners').to.be.an('array') + chai.expect(safeInfoResponse).to.have.property('modules').to.be.an('array') + chai.expect(safeInfoResponse.fallbackHandler).to.eq(API_TESTING_SAFE.fallbackHandler) + chai.expect(safeInfoResponse.guard).to.eq(API_TESTING_SAFE.guard) + chai.expect(safeInfoResponse.version).to.eq(API_TESTING_SAFE.version) + chai.expect(safeInfoResponse).to.have.property('singleton').to.eq(API_TESTING_SAFE.singleton) + // FIXME currently the service returns masterCopy and we replace it by singleton on SafeApiKit. + // To avoid the breaking change they will return both propertys for a while, when this happens we can remove the hack at SafApiKit. + // The test will fail at that moment. + chai.expect(safeInfoResponse).not.to.have.property('masterCopy') }) }) diff --git a/packages/api-kit/tests/e2e/getSafesByModule.test.ts b/packages/api-kit/tests/e2e/getSafesByModule.test.ts index 856d96563..80e46f3cb 100644 --- a/packages/api-kit/tests/e2e/getSafesByModule.test.ts +++ b/packages/api-kit/tests/e2e/getSafesByModule.test.ts @@ -7,7 +7,7 @@ import { getApiKit } from '../utils/setupKits' chai.use(chaiAsPromised) let safeApiKit: SafeApiKit -const goerliSpendingLimitModule = '0xCFbFaC74C26F8647cBDb8c5caf80BB5b32E43134' +const allowanceModule = '0xCFbFaC74C26F8647cBDb8c5caf80BB5b32E43134' describe('getSafesByModule', () => { before(async () => { @@ -36,14 +36,14 @@ describe('getSafesByModule', () => { }) it('should return the array Safes with the module enabled', async () => { - const moduleAddress = goerliSpendingLimitModule + const moduleAddress = allowanceModule const moduleResponse = await safeApiKit.getSafesByModule(moduleAddress) const { safes } = moduleResponse chai.expect(safes.length).to.be.greaterThan(10) }) it('should return the array of Safes with the module enabled when using EIP-3770 module address', async () => { - const moduleAddress = goerliSpendingLimitModule + const moduleAddress = allowanceModule const eip3770ModuleAddress = `${config.EIP_3770_PREFIX}:${moduleAddress}` const moduleResponse = await safeApiKit.getSafesByModule(eip3770ModuleAddress) const { safes } = moduleResponse diff --git a/packages/api-kit/tests/e2e/getServiceInfo.test.ts b/packages/api-kit/tests/e2e/getServiceInfo.test.ts index 7074ff3d3..2b4c42140 100644 --- a/packages/api-kit/tests/e2e/getServiceInfo.test.ts +++ b/packages/api-kit/tests/e2e/getServiceInfo.test.ts @@ -9,8 +9,8 @@ describe('getServiceInfo', () => { safeApiKit = getApiKit() }) - it('should return the Safe info', async () => { - const safeInfo = await safeApiKit.getServiceInfo() - expect(safeInfo.api_version).to.be.equal('v1') + it('should return the Safe service info', async () => { + const serviceInfo = await safeApiKit.getServiceInfo() + expect(serviceInfo.api_version).to.be.equal('v1') }) }) diff --git a/packages/api-kit/tests/helpers/safe.ts b/packages/api-kit/tests/helpers/safe.ts new file mode 100644 index 000000000..62a0b77de --- /dev/null +++ b/packages/api-kit/tests/helpers/safe.ts @@ -0,0 +1,15 @@ +export const API_TESTING_SAFE = { + address: '0xF8ef84392f7542576F6b9d1b140334144930Ac78', + nonce: 11, + threshold: 2, + owners: [ + '0x56e2C102c664De6DfD7315d12c0178b61D16F171', + '0x9cCBDE03eDd71074ea9c49e413FA9CDfF16D263B', + '0xDa8dd250065F19f7A29564396D7F13230b9fC5A3' + ], + modules: [], + fallbackHandler: '0x017062a1dE2FE6b99BE3d9d37841FeD19F573804', + guard: '0x0000000000000000000000000000000000000000', + version: '1.3.0+L2', + singleton: '0xfb1bffC9d739B8D520DaF37dF666da4C687191EA' +} diff --git a/packages/types-kit/src/types.ts b/packages/types-kit/src/types.ts index cec7c4ca5..4d9050020 100644 --- a/packages/types-kit/src/types.ts +++ b/packages/types-kit/src/types.ts @@ -214,6 +214,17 @@ export type ListResponse = { } export type SafeMultisigConfirmationListResponse = ListResponse +export type DataDecoded = { + readonly method: string + readonly parameters: DecodedParameters[] +} + +export type DecodedParameters = { + readonly name: string + readonly type: string + readonly value: string +} + export type SafeMultisigTransactionResponse = { readonly safe: string readonly to: string @@ -233,14 +244,17 @@ export type SafeMultisigTransactionResponse = { readonly transactionHash: string readonly safeTxHash: string readonly executor?: string - readonly proposer: string + readonly proposer?: string + readonly proposedByDelegate?: string readonly isExecuted: boolean readonly isSuccessful?: boolean readonly ethGasPrice?: string + readonly maxFeePerGas?: string + readonly maxPriorityFeePerGas?: string readonly gasUsed?: number readonly fee?: string readonly origin: string - readonly dataDecoded?: string + readonly dataDecoded?: DataDecoded readonly confirmationsRequired: number readonly confirmations?: SafeMultisigConfirmationResponse[] readonly trusted: boolean From c9a7eeedef40a256721e3e927e0072997e289cfe Mon Sep 17 00:00:00 2001 From: Daniel <25051234+dasanra@users.noreply.github.com> Date: Fri, 17 Jan 2025 12:03:19 +0100 Subject: [PATCH 2/3] fix: test failing by locally added property --- packages/api-kit/tests/endpoint/index.test.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/api-kit/tests/endpoint/index.test.ts b/packages/api-kit/tests/endpoint/index.test.ts index 229324ccd..9e34c2feb 100644 --- a/packages/api-kit/tests/endpoint/index.test.ts +++ b/packages/api-kit/tests/endpoint/index.test.ts @@ -170,7 +170,9 @@ describe('Endpoint tests', () => { it('getSafeInfo', async () => { await chai .expect(safeApiKit.getSafeInfo(safeAddress)) - .to.be.eventually.deep.equals({ data: { success: true } }) + // FIXME the singleton hack makes that the property is always added by SafeApiKit. + // Remove when is correctly returned by the service. + .to.be.eventually.deep.equals({ data: { success: true }, singleton: undefined }) chai.expect(fetchData).to.have.been.calledWith({ url: `${txServiceBaseUrl}/v1/safes/${safeAddress}/`, method: 'get' @@ -180,7 +182,9 @@ describe('Endpoint tests', () => { it('getSafeInfo EIP-3770', async () => { await chai .expect(safeApiKit.getSafeInfo(eip3770SafeAddress)) - .to.be.eventually.deep.equals({ data: { success: true } }) + // FIXME the singleton hack makes that the property is always added by SafeApiKit. + // Remove when is correctly returned by the service. + .to.be.eventually.deep.equals({ data: { success: true }, singleton: undefined }) chai.expect(fetchData).to.have.been.calledWith({ url: `${txServiceBaseUrl}/v1/safes/${safeAddress}/`, method: 'get' From 5375010c8f4c9983c96a9280d5a14b5e19baeeea Mon Sep 17 00:00:00 2001 From: Daniel <25051234+dasanra@users.noreply.github.com> Date: Wed, 22 Jan 2025 12:50:46 +0100 Subject: [PATCH 3/3] chore(api-kit): update comment to be more explicti --- packages/api-kit/src/SafeApiKit.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api-kit/src/SafeApiKit.ts b/packages/api-kit/src/SafeApiKit.ts index 004315501..5e6babc8a 100644 --- a/packages/api-kit/src/SafeApiKit.ts +++ b/packages/api-kit/src/SafeApiKit.ts @@ -259,7 +259,7 @@ class SafeApiKit { url: `${this.#txServiceBaseUrl}/v1/safes/${address}/`, method: HttpMethod.Get }).then((response: any) => { - // FIXME remove when service returns the singleton property + // FIXME remove when the transaction service returns the singleton property instead of masterCopy if (!response?.singleton) { const { masterCopy, ...rest } = response return { ...rest, singleton: masterCopy } as SafeInfoResponse