Skip to content

Commit

Permalink
fix(api-kit): add missing properties to types (#1100)
Browse files Browse the repository at this point in the history
  • Loading branch information
dasanra authored Jan 22, 2025
1 parent f9d655c commit ebfbfc9
Show file tree
Hide file tree
Showing 15 changed files with 152 additions and 61 deletions.
8 changes: 8 additions & 0 deletions packages/api-kit/src/SafeApiKit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,14 @@ class SafeApiKit {
return sendRequest({
url: `${this.#txServiceBaseUrl}/v1/safes/${address}/`,
method: HttpMethod.Get
}).then((response: any) => {
// 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
}

return response as SafeInfoResponse
})
}

Expand Down
48 changes: 20 additions & 28 deletions packages/api-kit/src/types/safeTransactionServiceTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,20 +134,6 @@ export type PendingTransactionsOptions = {

export type SafeMultisigTransactionListResponse = ListResponse<SafeMultisigTransactionResponse>

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<TransferResponse>

export type SafeModuleTransaction = {
readonly created?: string
readonly executionDate: string
Expand All @@ -165,36 +151,42 @@ export type SafeModuleTransaction = {

export type SafeModuleTransactionListResponse = ListResponse<SafeModuleTransaction>

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<TransferResponse>

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<TokenInfoResponse>

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 = {
Expand All @@ -208,7 +200,7 @@ export type EthereumTxResponse = {

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

export type AllTransactionsOptions = {
Expand Down
3 changes: 2 additions & 1 deletion packages/api-kit/tests/e2e/addMessageSignature.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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 => {
Expand Down
13 changes: 7 additions & 6 deletions packages/api-kit/tests/e2e/addSafeDelegate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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 = {
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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}`
Expand Down
37 changes: 34 additions & 3 deletions packages/api-kit/tests/e2e/getIncomingTransactions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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')
Expand All @@ -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
}
})
})
})
3 changes: 2 additions & 1 deletion packages/api-kit/tests/e2e/getMessage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down
3 changes: 2 additions & 1 deletion packages/api-kit/tests/e2e/getMessages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down
10 changes: 6 additions & 4 deletions packages/api-kit/tests/e2e/getNextNonce.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/api-kit/tests/e2e/getSafeDelegates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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')
Expand Down Expand Up @@ -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`,
Expand Down
31 changes: 26 additions & 5 deletions packages/api-kit/tests/e2e/getSafeInfo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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')
})
})
Loading

0 comments on commit ebfbfc9

Please sign in to comment.