Skip to content

Commit

Permalink
wip: tx types fixin
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasbrugneaux committed Oct 30, 2023
1 parent 6f48bd0 commit fb17e68
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 105 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
Expand Down
82 changes: 80 additions & 2 deletions src/chains/celo/formatters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,6 @@ describe('transactionRequest', () => {
maxFeePerGas: 2n,
maxPriorityFeePerGas: 1n,
nonce: 1,
type: 'cip42',
value: 1n,
}),
).toMatchInlineSnapshot(`
Expand All @@ -846,7 +845,6 @@ describe('transactionRequest', () => {
maxFeePerGas: 2n,
maxPriorityFeePerGas: 1n,
nonce: 1,
type: 'cip64',
value: 1n,
}),
).toMatchInlineSnapshot(`
Expand All @@ -862,5 +860,85 @@ describe('transactionRequest', () => {
"value": "0x1",
}
`)

expect(
transactionRequest.format({
from: '0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9',
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', // Recipient (illustrative address)
value: 1n,
feeCurrency: '0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1', // cUSD fee currency
maxFeePerGas: 2n, // Special field for dynamic fee transaction type (EIP-1559)
maxPriorityFeePerGas: 2n, // Special field for dynamic fee transaction type (EIP-1559)
}),
).toMatchInlineSnapshot(`
{
"feeCurrency": "0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1",
"from": "0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9",
"gas": undefined,
"gasPrice": undefined,
"maxFeePerGas": "0x2",
"maxPriorityFeePerGas": "0x2",
"nonce": undefined,
"to": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
"type": "0x7b",
"value": "0x1",
}
`)

expect(
transactionRequest.format({
feeCurrency: '0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9',
from: '0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9',
gas: 1n,
gatewayFee: 4n,
gatewayFeeRecipient: '0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9',
maxFeePerGas: 2n,
maxPriorityFeePerGas: 1n,
nonce: 1,
value: 1n,
}),
).toMatchInlineSnapshot(`
{
"feeCurrency": "0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9",
"from": "0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9",
"gas": "0x1",
"gasPrice": undefined,
"gatewayFee": "0x4",
"gatewayFeeRecipient": "0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9",
"maxFeePerGas": "0x2",
"maxPriorityFeePerGas": "0x1",
"nonce": "0x1",
"type": "0x7c",
"value": "0x1",
}
`)

expect(
transactionRequest.format({
feeCurrency: '0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9',
from: '0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9',
gas: 1n,
gatewayFee: 4n,
gatewayFeeRecipient: '0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9',
maxFeePerGas: 2n,
maxPriorityFeePerGas: 4n,
nonce: 1,
value: 1n,
}),
).toMatchInlineSnapshot(`
{
"feeCurrency": "0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9",
"from": "0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9",
"gas": "0x1",
"gasPrice": undefined,
"gatewayFee": "0x4",
"gatewayFeeRecipient": "0x0f16e9b0d03470827a95cdfd0cb8a8a3b46969b9",
"maxFeePerGas": "0x2",
"maxPriorityFeePerGas": "0x4",
"nonce": "0x1",
"type": "0x7c",
"value": "0x1",
}
`)
})
})
21 changes: 3 additions & 18 deletions src/chains/celo/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,7 @@ import type {
CeloTransactionReceiptOverrides,
CeloTransactionRequest,
} from './types.js'

function isTransactionRequestCIP64(args: CeloTransactionRequest): boolean {
if (args.type === 'cip64') return true
if (args.type) return false
return (
'feeCurrency' in args &&
args.gatewayFee === undefined &&
args.gatewayFeeRecipient === undefined
)
}

function isTransactionRequestCIP42(args: CeloTransactionRequest): boolean {
if (args.type === 'cip42') return true
if (args.type) return false
return args.gatewayFee !== undefined || args.gatewayFeeRecipient !== undefined
}
import { isCIP42, isCIP64 } from './utils.js'

export const formattersCelo = {
block: /*#__PURE__*/ defineBlock({
Expand Down Expand Up @@ -95,7 +80,7 @@ export const formattersCelo = {

transactionRequest: /*#__PURE__*/ defineTransactionRequest({
format(args: CeloTransactionRequest): CeloRpcTransactionRequest {
if (isTransactionRequestCIP64(args))
if (isCIP64(args))
return {
type: '0x7b',
feeCurrency: args.feeCurrency,
Expand All @@ -110,7 +95,7 @@ export const formattersCelo = {
gatewayFeeRecipient: args.gatewayFeeRecipient,
} as CeloRpcTransactionRequest

if (isTransactionRequestCIP42(args)) request.type = '0x7c'
if (isCIP42(args)) request.type = '0x7c'

return request
},
Expand Down
125 changes: 88 additions & 37 deletions src/chains/celo/serializers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,22 @@ const commonBaseTx = {
feeCurrency: '0x765de816845861e75a25fca122bb6898b8b1282a',
value: parseEther('1'),
}

const baseCip42 = {
...commonBaseTx,
type: 'cip42',
gatewayFee: parseGwei('2'),
gatewayFeeRecipient: '0x0000000000000000000000000000000000000000',
} as TransactionSerializableCIP42

const baseCip64 = {
...commonBaseTx,
type: 'cip64',
maxFeePerGas: parseGwei('2'),
maxPriorityFeePerGas: parseGwei('2'),
} as TransactionSerializableCIP64

describe('cip42', () => {
test('should be able to serialize a cip42 transaction', () => {
const transaction: TransactionSerializableCIP42 = {
...baseCip42,
}

expect(serializeTransactionCelo(transaction)).toEqual(
expect(serializeTransactionCelo(baseCip42)).toEqual(
'0x7cf84682a4ec80847735940084773594008094765de816845861e75a25fca122bb6898b8b1282a808094f39fd6e51aad88f6f4ce6ab8827279cfffb92266880de0b6b3a764000080c0',
)
})
Expand Down Expand Up @@ -443,15 +442,77 @@ describe('invalid params specific to CIP-64', () => {
})
})

describe.each([
{ typeName: 'CIP-42', baseTransaction: baseCip42 },
{ typeName: 'CIP-64', baseTransaction: baseCip64 },
])('Common invalid params (for $typeName)', ({ typeName, baseTransaction }) => {
describe('Common invalid params (for CIP-42)', () => {
test('invalid to', () => {
const transaction: TransactionSerializableCIP42 = {
...baseCip42,
to: '0xdeadbeef',
}
expect(() => serializeTransactionCelo(transaction)).toThrowError(
InvalidAddressError,
)
})

test('gatewayFeeRecipient is not an address', () => {
const transaction: TransactionSerializableCIP42 = {
...baseCip42,
// @ts-expect-error - (Type '"example"' is not assignable to type "`0x${string}"'
gatewayFeeRecipient: 'example',
}
expect(() => serializeTransactionCelo(transaction)).toThrowError(
TipAboveFeeCapError,
)
})

test('maxFeePerGas is too high', () => {
const transaction: TransactionSerializableCIP42 = {
...baseCip42,
}
expect(() => serializeTransactionCelo(transaction)).toThrowError(
FeeCapTooHighError,
)
})

test('feeCurrency is not an address', () => {
const transaction: TransactionSerializableCIP42 = {
...baseCip42,
// @ts-expect-error - (Type '"CUSD"' is not assignable to type "`0x${string}"'
feeCurrency: 'CUSD',
}

expect(() => serializeTransactionCelo(transaction)).toThrowError(
'`feeCurrency` MUST be a token address for CIP-42 transactions.',
)
})

test('gasPrice is defined', () => {
const transaction: TransactionSerializableCIP42 = {
...baseCip42,
// @ts-expect-error
gasPrice: BigInt(1),
}

expect(() => serializeTransactionCelo(transaction)).toThrowError(
'`gasPrice` is not a valid CIP-42 Transaction attribute.',
)
})

test('chainID is invalid', () => {
const transaction: TransactionSerializableCIP42 = {
...baseCip42,
chainId: -1,
}

expect(() => serializeTransactionCelo(transaction)).toThrowError(
`Chain ID "${-1}" is invalid.`,
)
})
})

describe('Common invalid params (for CIP-64)', () => {
test('invalid to', () => {
const transaction:
| TransactionSerializableCIP42
| TransactionSerializableCIP64 = {
...baseTransaction,
const transaction: TransactionSerializableCIP64 = {
...baseCip64,
to: '0xdeadbeef',
}
expect(() => serializeTransactionCelo(transaction)).toThrowError(
Expand All @@ -460,10 +521,8 @@ describe.each([
})

test('maxPriorityFeePerGas is higher than maxPriorityFee', () => {
const transaction:
| TransactionSerializableCIP42
| TransactionSerializableCIP64 = {
...baseTransaction,
const transaction: TransactionSerializableCIP64 = {
...baseCip64,
maxPriorityFeePerGas: parseGwei('5000000000'),
maxFeePerGas: parseGwei('1'),
}
Expand All @@ -473,10 +532,8 @@ describe.each([
})

test('maxFeePerGas is too high', () => {
const transaction:
| TransactionSerializableCIP42
| TransactionSerializableCIP64 = {
...baseTransaction,
const transaction: TransactionSerializableCIP64 = {
...baseCip64,
maxPriorityFeePerGas: parseGwei('5000000000'),
maxFeePerGas:
115792089237316195423570985008687907853269984665640564039457584007913129639938n,
Expand All @@ -487,38 +544,32 @@ describe.each([
})

test('feeCurrency is not an address', () => {
const transaction:
| TransactionSerializableCIP42
| TransactionSerializableCIP64 = {
...baseTransaction,
const transaction: TransactionSerializableCIP64 = {
...baseCip64,
// @ts-expect-error
feeCurrency: 'CUSD',
}

expect(() => serializeTransactionCelo(transaction)).toThrowError(
`\`feeCurrency\` MUST be a token address for ${typeName} transactions.`,
'`feeCurrency` MUST be a token address for CIP-64 transactions.',
)
})

test('gasPrice is defined', () => {
const transaction:
| TransactionSerializableCIP42
| TransactionSerializableCIP64 = {
...baseTransaction,
const transaction: TransactionSerializableCIP64 = {
...baseCip64,
// @ts-expect-error
gasPrice: BigInt(1),
}

expect(() => serializeTransactionCelo(transaction)).toThrowError(
`\`gasPrice\` is not a valid ${typeName} Transaction attribute.`,
'`gasPrice` is not a valid CIP-64 Transaction attribute.',
)
})

test('chainID is invalid', () => {
const transaction:
| TransactionSerializableCIP42
| TransactionSerializableCIP64 = {
...baseTransaction,
const transaction: TransactionSerializableCIP64 = {
...baseCip64,
chainId: -1,
}

Expand Down
Loading

0 comments on commit fb17e68

Please sign in to comment.