diff --git a/.changeset/grumpy-swans-judge.md b/.changeset/grumpy-swans-judge.md new file mode 100644 index 0000000..957b2be --- /dev/null +++ b/.changeset/grumpy-swans-judge.md @@ -0,0 +1,5 @@ +--- +"@across-protocol/integrator-sdk": patch +--- + +stricter integrator id check diff --git a/apps/example/app/ethers/components/Bridge.tsx b/apps/example/app/ethers/components/Bridge.tsx index 343f344..390822d 100644 --- a/apps/example/app/ethers/components/Bridge.tsx +++ b/apps/example/app/ethers/components/Bridge.tsx @@ -17,7 +17,6 @@ const chains = [mainnet, arbitrum]; const sdk = AcrossClient.create({ chains, useTestnet: false, - integratorId: "TEST", logLevel: "DEBUG", }); diff --git a/apps/example/lib/across.tsx b/apps/example/lib/across.tsx index db0965e..ff3a46b 100644 --- a/apps/example/lib/across.tsx +++ b/apps/example/lib/across.tsx @@ -9,7 +9,6 @@ export const SUPPORTED_CHAINS = MAINNET_SUPPORTED_CHAINS; const sdk = AcrossClient.create({ chains: [...SUPPORTED_CHAINS], useTestnet: false, - integratorId: "TEST", logLevel: "DEBUG", }); diff --git a/apps/example/scripts/sdk.ts b/apps/example/scripts/sdk.ts index cca91c2..9130dfb 100644 --- a/apps/example/scripts/sdk.ts +++ b/apps/example/scripts/sdk.ts @@ -46,7 +46,6 @@ async function main() { const client = AcrossClient.create({ chains, useTestnet: false, - integratorId: "TEST", logLevel: "DEBUG", walletClient, tenderly: { diff --git a/packages/sdk/src/actions/executeQuote.ts b/packages/sdk/src/actions/executeQuote.ts index 0c86614..8b07b9c 100644 --- a/packages/sdk/src/actions/executeQuote.ts +++ b/packages/sdk/src/actions/executeQuote.ts @@ -1,6 +1,7 @@ import { Address, Hash, + Hex, parseAbi, SimulateContractReturnType, TransactionReceipt, @@ -112,7 +113,7 @@ export type ExecuteQuoteParams = { /** * An identifier for the integrator. */ - integratorId: string; + integratorId: Hex; /** * The deposit to execute. Should be taken from return value of {@link getQuote}. */ diff --git a/packages/sdk/src/actions/simulateDepositTx.ts b/packages/sdk/src/actions/simulateDepositTx.ts index ebee073..49e58ad 100644 --- a/packages/sdk/src/actions/simulateDepositTx.ts +++ b/packages/sdk/src/actions/simulateDepositTx.ts @@ -1,4 +1,5 @@ import { + Hex, PublicClient, SimulateContractReturnType, WalletClient, @@ -18,7 +19,7 @@ export type SimulateDepositTxParams = { deposit: Quote["deposit"] & { fillDeadline?: number; }; - integratorId: string; + integratorId: Hex; logger?: LoggerT; }; diff --git a/packages/sdk/src/client.ts b/packages/sdk/src/client.ts index 60133d9..a28ad43 100644 --- a/packages/sdk/src/client.ts +++ b/packages/sdk/src/client.ts @@ -2,6 +2,7 @@ import { Chain, ContractFunctionExecutionError, encodeFunctionData, + Hex, } from "viem"; import { getAvailableRoutes, @@ -43,6 +44,7 @@ import { getSupportedChains, simulateTxOnTenderly, TenderlySimulateTxParams, + assertValidIntegratorId, } from "./utils"; import { AcrossApiSimulationError, @@ -53,12 +55,11 @@ import { ConfiguredPublicClient, ConfiguredPublicClientMap, ConfiguredWalletClient, - Deposit, } from "./types"; const CLIENT_DEFAULTS = { pollingInterval: 3_000, - integratorId: "INTEGRATOR_SDK", + integratorId: "0xdead", logLevel: "ERROR", } as const; @@ -67,7 +68,7 @@ export type AcrossClientOptions = { /** * An identifier representing the integrator. */ - integratorId?: string; + integratorId?: Hex; /** * The chains to use for the Across API. Should be imported from `viem/chains`. */ @@ -135,7 +136,7 @@ export type AcrossClientOptions = { export class AcrossClient { private static instance: AcrossClient | null = null; - private integratorId: string; + private integratorId: Hex; private publicClients: ConfiguredPublicClientMap; private walletClient?: ConfiguredWalletClient; private apiUrl: string; @@ -159,7 +160,10 @@ export class AcrossClient { } private constructor(args: AcrossClientOptions) { - this.integratorId = args?.integratorId ?? CLIENT_DEFAULTS.integratorId; + const integratorId = args?.integratorId ?? CLIENT_DEFAULTS.integratorId; + assertValidIntegratorId(integratorId); + + this.integratorId = integratorId; this.walletClient = args?.walletClient; this.publicClients = configurePublicClients( args.chains, diff --git a/packages/sdk/src/utils/hex.ts b/packages/sdk/src/utils/hex.ts index 6c3d768..77e7314 100644 --- a/packages/sdk/src/utils/hex.ts +++ b/packages/sdk/src/utils/hex.ts @@ -1,11 +1,35 @@ -import { concat, Hex, toHex } from "viem"; +import { concat, Hex, isHex } from "viem"; export const DOMAIN_CALLDATA_DELIMITER = "0x1dc0de"; -export function tagIntegratorId(integratorId: string, txData: Hex) { - return concat([txData, DOMAIN_CALLDATA_DELIMITER, toHex(integratorId)]); +export function tagIntegratorId(integratorId: Hex, txData: Hex) { + assertValidIntegratorId(integratorId); + + return concat([txData, DOMAIN_CALLDATA_DELIMITER, integratorId]); +} + +export function getIntegratorDataSuffix(integratorId: Hex) { + assertValidIntegratorId(integratorId); + + return concat([DOMAIN_CALLDATA_DELIMITER, integratorId]); } -export function getIntegratorDataSuffix(integratorId: string) { - return concat([DOMAIN_CALLDATA_DELIMITER, toHex(integratorId)]); +export function isValidIntegratorId(integratorId: string) { + return ( + isHex(integratorId) && + // "0x" + 2 bytes = 6 hex characters + integratorId.length === 6 + ); +} + +export function assertValidIntegratorId( + integratorId: string, +): integratorId is Hex { + if (!isValidIntegratorId(integratorId)) { + throw new Error( + `Invalid integrator ID: ${integratorId}. Needs to be 2 bytes hex string.`, + ); + } + + return true; } diff --git a/packages/sdk/test/utils/logger.test.ts b/packages/sdk/test/utils/logger.test.ts index 999994c..26d8887 100644 --- a/packages/sdk/test/utils/logger.test.ts +++ b/packages/sdk/test/utils/logger.test.ts @@ -4,7 +4,6 @@ import { hardhat } from "viem/chains"; const client = AcrossClient.create({ useTestnet: true, - integratorId: "TEST_ID", logLevel: "WARN", chains: [hardhat], });