@xswap-link/sdk 0.10.8 → 0.10.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +10 -1
- package/CHANGELOG.md +12 -0
- package/dist/index.global.js +331 -331
- package/dist/index.js +9 -9
- package/dist/index.mjs +9 -9
- package/package.json +6 -3
- package/src/components/Swap/SwapView/ConfirmationView/TxOverview/index.tsx +106 -9
- package/src/components/Swap/SwapView/SwapButton/index.tsx +11 -11
- package/src/constants/index.ts +18 -0
- package/src/context/SwapProvider.tsx +7 -3
- package/src/services/api.ts +1 -0
- package/src/services/svm/README.md +483 -0
- package/src/services/svm/bindings/accounts/AllowedOfframp.ts +73 -0
- package/src/services/svm/bindings/accounts/Config.ts +153 -0
- package/src/services/svm/bindings/accounts/DestChain.ts +113 -0
- package/src/services/svm/bindings/accounts/Nonce.ts +97 -0
- package/src/services/svm/bindings/accounts/index.ts +15 -0
- package/src/services/svm/bindings/accounts/tokenAdminRegistry.ts +128 -0
- package/src/services/svm/bindings/errors/anchor.ts +773 -0
- package/src/services/svm/bindings/errors/custom.ts +375 -0
- package/src/services/svm/bindings/errors/index.ts +62 -0
- package/src/services/svm/bindings/instructions/ccipSend.ts +112 -0
- package/src/services/svm/bindings/instructions/getFee.ts +73 -0
- package/src/services/svm/bindings/instructions/index.ts +4 -0
- package/src/services/svm/bindings/programId.ts +6 -0
- package/src/services/svm/bindings/types/BaseChain.ts +92 -0
- package/src/services/svm/bindings/types/BaseConfig.ts +184 -0
- package/src/services/svm/bindings/types/CodeVersion.ts +88 -0
- package/src/services/svm/bindings/types/CrossChainAmount.ts +53 -0
- package/src/services/svm/bindings/types/DestChainConfig.ts +76 -0
- package/src/services/svm/bindings/types/DestChainState.ts +76 -0
- package/src/services/svm/bindings/types/GetFeeResult.ts +72 -0
- package/src/services/svm/bindings/types/LockOrBurnInV1.ts +102 -0
- package/src/services/svm/bindings/types/LockOrBurnOutV1.ts +79 -0
- package/src/services/svm/bindings/types/RampMessageHeader.ts +94 -0
- package/src/services/svm/bindings/types/RateLimitConfig.ts +72 -0
- package/src/services/svm/bindings/types/RateLimitTokenBucket.ts +76 -0
- package/src/services/svm/bindings/types/ReleaseOrMintInV1.ts +156 -0
- package/src/services/svm/bindings/types/ReleaseOrMintOutV1.ts +53 -0
- package/src/services/svm/bindings/types/RemoteAddress.ts +61 -0
- package/src/services/svm/bindings/types/RemoteConfig.ts +86 -0
- package/src/services/svm/bindings/types/RestoreOnAction.ts +120 -0
- package/src/services/svm/bindings/types/SVM2AnyMessage.ts +128 -0
- package/src/services/svm/bindings/types/SVM2AnyRampMessage.ts +166 -0
- package/src/services/svm/bindings/types/SVM2AnyTokenTransfer.ts +118 -0
- package/src/services/svm/bindings/types/SVMTokenAmount.ts +64 -0
- package/src/services/svm/bindings/types/index.ts +78 -0
- package/src/services/svm/core/client/accounts.ts +97 -0
- package/src/services/svm/core/client/events.ts +95 -0
- package/src/services/svm/core/client/fee.ts +279 -0
- package/src/services/svm/core/client/index.ts +150 -0
- package/src/services/svm/core/client/send.ts +607 -0
- package/src/services/svm/core/client/utils.ts +131 -0
- package/src/services/svm/core/models.ts +236 -0
- package/src/services/svm/index.ts +32 -0
- package/src/services/svm/utils/conversion.ts +62 -0
- package/src/services/svm/utils/errors.ts +51 -0
- package/src/services/svm/utils/keypair.ts +19 -0
- package/src/services/svm/utils/logger.ts +171 -0
- package/src/services/svm/utils/pdas/common.ts +15 -0
- package/src/services/svm/utils/pdas/feeQuoter.ts +68 -0
- package/src/services/svm/utils/pdas/index.ts +12 -0
- package/src/services/svm/utils/pdas/receiver.ts +58 -0
- package/src/services/svm/utils/pdas/rmnRemote.ts +23 -0
- package/src/services/svm/utils/pdas/router.ts +328 -0
- package/src/services/svm/utils/pdas/tokenpool.ts +161 -0
- package/src/services/svm/utils/transaction.ts +132 -0
- package/src/utils/validation.ts +7 -3
- package/tsconfig.json +2 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common utilities for PDA derivation
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Converts a u64 to 8-byte little endian buffer
|
|
7
|
+
* @param n - Number to convert
|
|
8
|
+
* @returns Buffer representation
|
|
9
|
+
*/
|
|
10
|
+
export function uint64ToLE(n: number | bigint): Buffer {
|
|
11
|
+
const bn = BigInt(n);
|
|
12
|
+
const buf = Buffer.alloc(8);
|
|
13
|
+
buf.writeBigUInt64LE(bn);
|
|
14
|
+
return buf;
|
|
15
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import { uint64ToLE } from "./common";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fee Quoter PDA utilities
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Finds the Fee Quoter Config PDA
|
|
10
|
+
* @param feeQuoter Fee Quoter program ID
|
|
11
|
+
* @returns [PDA, bump]
|
|
12
|
+
*/
|
|
13
|
+
export function findFqConfigPDA(feeQuoter: PublicKey): [PublicKey, number] {
|
|
14
|
+
return PublicKey.findProgramAddressSync([Buffer.from("config")], feeQuoter);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Finds the Fee Quoter Dest Chain PDA for a chain selector
|
|
19
|
+
* @param chainSelector Chain selector
|
|
20
|
+
* @param feeQuoter Fee Quoter program ID
|
|
21
|
+
* @returns [PDA, bump]
|
|
22
|
+
*/
|
|
23
|
+
export function findFqDestChainPDA(chainSelector: bigint, feeQuoter: PublicKey): [PublicKey, number] {
|
|
24
|
+
return PublicKey.findProgramAddressSync(
|
|
25
|
+
[Buffer.from("dest_chain"), uint64ToLE(chainSelector)],
|
|
26
|
+
feeQuoter
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Finds the Fee Quoter Billing Token Config PDA for a mint
|
|
32
|
+
* @param mint Token mint
|
|
33
|
+
* @param feeQuoter Fee Quoter program ID
|
|
34
|
+
* @returns [PDA, bump]
|
|
35
|
+
*/
|
|
36
|
+
export function findFqBillingTokenConfigPDA(mint: PublicKey, feeQuoter: PublicKey): [PublicKey, number] {
|
|
37
|
+
return PublicKey.findProgramAddressSync(
|
|
38
|
+
[Buffer.from("fee_billing_token_config"), mint.toBuffer()],
|
|
39
|
+
feeQuoter
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Finds the Fee Quoter Per Chain Per Token Config PDA for a chain selector and mint
|
|
45
|
+
* @param chainSelector Chain selector
|
|
46
|
+
* @param mint Token mint
|
|
47
|
+
* @param feeQuoter Fee Quoter program ID
|
|
48
|
+
* @returns [PDA, bump]
|
|
49
|
+
*/
|
|
50
|
+
export function findFqPerChainPerTokenConfigPDA(chainSelector: bigint, mint: PublicKey, feeQuoter: PublicKey): [PublicKey, number] {
|
|
51
|
+
return PublicKey.findProgramAddressSync(
|
|
52
|
+
[Buffer.from("per_chain_per_token_config"), uint64ToLE(chainSelector), mint.toBuffer()],
|
|
53
|
+
feeQuoter
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Finds the Fee Quoter Allowed Price Updater PDA for a price updater
|
|
59
|
+
* @param priceUpdater Price updater public key
|
|
60
|
+
* @param feeQuoter Fee Quoter program ID
|
|
61
|
+
* @returns [PDA, bump]
|
|
62
|
+
*/
|
|
63
|
+
export function findFqAllowedPriceUpdaterPDA(priceUpdater: PublicKey, feeQuoter: PublicKey): [PublicKey, number] {
|
|
64
|
+
return PublicKey.findProgramAddressSync(
|
|
65
|
+
[Buffer.from("allowed_price_updater"), priceUpdater.toBuffer()],
|
|
66
|
+
feeQuoter
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PDA utilities for CCIP and related programs
|
|
3
|
+
* This module exports all PDA-related functionality in a unified way
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Export all PDA modules
|
|
7
|
+
export * from "./router";
|
|
8
|
+
export * from "./feeQuoter";
|
|
9
|
+
export * from "./rmnRemote";
|
|
10
|
+
export * from "./common";
|
|
11
|
+
export * from "./receiver";
|
|
12
|
+
export * from "./tokenpool";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CCIP Receiver PDA utilities
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Seeds for the CCIP receiver program
|
|
8
|
+
export const RECEIVER_SEEDS = {
|
|
9
|
+
EXTERNAL_EXECUTION_CONFIG: Buffer.from("external_execution_config"),
|
|
10
|
+
STATE: Buffer.from("state"),
|
|
11
|
+
CONFIG: Buffer.from("config"),
|
|
12
|
+
DEST_CHAIN_STATE: Buffer.from("dest_chain_state"),
|
|
13
|
+
FEE_BILLING_SIGNER: Buffer.from("fee_billing_signer"),
|
|
14
|
+
NONCE: Buffer.from("nonce"),
|
|
15
|
+
FEE_BILLING_TOKEN_CONFIG: Buffer.from("fee_billing_token_config"),
|
|
16
|
+
CURSES: Buffer.from("curses"),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Derives the state PDA for a CCIP receiver program
|
|
21
|
+
* @param programId Receiver program ID
|
|
22
|
+
* @returns State PDA
|
|
23
|
+
*/
|
|
24
|
+
export function deriveStatePda(programId: PublicKey): PublicKey {
|
|
25
|
+
const [statePda] = PublicKey.findProgramAddressSync(
|
|
26
|
+
[RECEIVER_SEEDS.STATE],
|
|
27
|
+
programId,
|
|
28
|
+
);
|
|
29
|
+
return statePda;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Derives the config PDA for a CCIP receiver program
|
|
34
|
+
* @param programId Receiver program ID
|
|
35
|
+
* @returns Config PDA
|
|
36
|
+
*/
|
|
37
|
+
export function deriveConfigPda(programId: PublicKey): PublicKey {
|
|
38
|
+
const [configPda] = PublicKey.findProgramAddressSync(
|
|
39
|
+
[RECEIVER_SEEDS.CONFIG],
|
|
40
|
+
programId,
|
|
41
|
+
);
|
|
42
|
+
return configPda;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Derives the external execution config PDA for a CCIP receiver program
|
|
47
|
+
* @param programId Receiver program ID
|
|
48
|
+
* @returns External execution config PDA
|
|
49
|
+
*/
|
|
50
|
+
export function deriveExternalExecutionConfigPda(
|
|
51
|
+
programId: PublicKey,
|
|
52
|
+
): PublicKey {
|
|
53
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
54
|
+
[RECEIVER_SEEDS.EXTERNAL_EXECUTION_CONFIG],
|
|
55
|
+
programId,
|
|
56
|
+
);
|
|
57
|
+
return pda;
|
|
58
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* RMN Remote PDA utilities
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Finds the RMN Remote Config PDA for a program
|
|
9
|
+
* @param programId RMN Remote program ID
|
|
10
|
+
* @returns [PDA, bump]
|
|
11
|
+
*/
|
|
12
|
+
export function findRMNRemoteConfigPDA(programId: PublicKey): [PublicKey, number] {
|
|
13
|
+
return PublicKey.findProgramAddressSync([Buffer.from("config")], programId);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Finds the RMN Remote Curses PDA for a program
|
|
18
|
+
* @param programId RMN Remote program ID
|
|
19
|
+
* @returns [PDA, bump]
|
|
20
|
+
*/
|
|
21
|
+
export function findRMNRemoteCursesPDA(programId: PublicKey): [PublicKey, number] {
|
|
22
|
+
return PublicKey.findProgramAddressSync([Buffer.from("curses")], programId);
|
|
23
|
+
}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { PublicKey } from "@solana/web3.js";
|
|
4
|
+
import { uint64ToLE } from "./common";
|
|
5
|
+
import { Connection } from "@solana/web3.js";
|
|
6
|
+
import { tokenAdminRegistry } from "../../bindings/accounts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* CCIP Router seeds for PDA derivation
|
|
10
|
+
*/
|
|
11
|
+
export const ROUTER_SEEDS = {
|
|
12
|
+
CONFIG: "config",
|
|
13
|
+
FEE_BILLING_SIGNER: "fee_billing_signer",
|
|
14
|
+
TOKEN_ADMIN_REGISTRY: "token_admin_registry",
|
|
15
|
+
DEST_CHAIN_STATE: "dest_chain_state",
|
|
16
|
+
NONCE: "nonce",
|
|
17
|
+
ALLOWED_OFFRAMP: "allowed_offramp",
|
|
18
|
+
EXTERNAL_TOKEN_POOLS_SIGNER: "external_token_pools_signer",
|
|
19
|
+
APPROVED_CCIP_SENDER: "approved_ccip_sender",
|
|
20
|
+
EXTERNAL_EXECUTION_CONFIG: "external_execution_config",
|
|
21
|
+
TOKEN_POOL_CHAIN_CONFIG: "ccip_tokenpool_chainconfig",
|
|
22
|
+
} as const;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* CCIP Router PDA utilities
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Finds the Config PDA for a program
|
|
30
|
+
* @param programId Router program ID
|
|
31
|
+
* @returns [PDA, bump]
|
|
32
|
+
*/
|
|
33
|
+
export function findConfigPDA(programId: PublicKey): [PublicKey, number] {
|
|
34
|
+
return PublicKey.findProgramAddressSync(
|
|
35
|
+
[Buffer.from(ROUTER_SEEDS.CONFIG)],
|
|
36
|
+
programId,
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Finds the Fee Billing Signer PDA for a program
|
|
42
|
+
* @param programId Router program ID
|
|
43
|
+
* @returns [PDA, bump]
|
|
44
|
+
*/
|
|
45
|
+
export function findFeeBillingSignerPDA(
|
|
46
|
+
programId: PublicKey,
|
|
47
|
+
): [PublicKey, number] {
|
|
48
|
+
return PublicKey.findProgramAddressSync(
|
|
49
|
+
[Buffer.from(ROUTER_SEEDS.FEE_BILLING_SIGNER)],
|
|
50
|
+
programId,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Finds the Token Admin Registry PDA for a mint
|
|
56
|
+
* @param mint Token mint
|
|
57
|
+
* @param programId Router program ID
|
|
58
|
+
* @returns [PDA, bump]
|
|
59
|
+
*/
|
|
60
|
+
export function findTokenAdminRegistryPDA(
|
|
61
|
+
mint: PublicKey,
|
|
62
|
+
programId: PublicKey,
|
|
63
|
+
): [PublicKey, number] {
|
|
64
|
+
return PublicKey.findProgramAddressSync(
|
|
65
|
+
[Buffer.from(ROUTER_SEEDS.TOKEN_ADMIN_REGISTRY), mint.toBuffer()],
|
|
66
|
+
programId,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Finds the Destination Chain State PDA for a chain selector
|
|
72
|
+
* @param chainSelector Chain selector
|
|
73
|
+
* @param programId Router program ID
|
|
74
|
+
* @returns [PDA, bump]
|
|
75
|
+
*/
|
|
76
|
+
export function findDestChainStatePDA(
|
|
77
|
+
chainSelector: bigint,
|
|
78
|
+
programId: PublicKey,
|
|
79
|
+
): [PublicKey, number] {
|
|
80
|
+
return PublicKey.findProgramAddressSync(
|
|
81
|
+
[Buffer.from(ROUTER_SEEDS.DEST_CHAIN_STATE), uint64ToLE(chainSelector)],
|
|
82
|
+
programId,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Finds the Nonce PDA for a chain selector and authority
|
|
88
|
+
* @param chainSelector Chain selector
|
|
89
|
+
* @param authority User authority
|
|
90
|
+
* @param programId Router program ID
|
|
91
|
+
* @returns [PDA, bump]
|
|
92
|
+
*/
|
|
93
|
+
export function findNoncePDA(
|
|
94
|
+
chainSelector: bigint,
|
|
95
|
+
authority: PublicKey,
|
|
96
|
+
programId: PublicKey,
|
|
97
|
+
): [PublicKey, number] {
|
|
98
|
+
return PublicKey.findProgramAddressSync(
|
|
99
|
+
[
|
|
100
|
+
Buffer.from(ROUTER_SEEDS.NONCE),
|
|
101
|
+
uint64ToLE(chainSelector),
|
|
102
|
+
authority.toBuffer(),
|
|
103
|
+
],
|
|
104
|
+
programId,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Finds the Approved Sender PDA for a chain selector and source sender
|
|
110
|
+
* @param chainSelector Chain selector
|
|
111
|
+
* @param sourceSender Source chain sender address
|
|
112
|
+
* @param receiverProgram Receiver program ID
|
|
113
|
+
* @returns [PDA, bump]
|
|
114
|
+
*/
|
|
115
|
+
export function findApprovedSenderPDA(
|
|
116
|
+
chainSelector: bigint,
|
|
117
|
+
sourceSender: Buffer,
|
|
118
|
+
receiverProgram: PublicKey,
|
|
119
|
+
): [PublicKey, number] {
|
|
120
|
+
const lenPrefix = Buffer.from([sourceSender.length]);
|
|
121
|
+
return PublicKey.findProgramAddressSync(
|
|
122
|
+
[
|
|
123
|
+
Buffer.from(ROUTER_SEEDS.APPROVED_CCIP_SENDER),
|
|
124
|
+
uint64ToLE(chainSelector),
|
|
125
|
+
lenPrefix,
|
|
126
|
+
sourceSender,
|
|
127
|
+
],
|
|
128
|
+
receiverProgram,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Finds the Allowed Offramp PDA for a chain selector and offramp
|
|
134
|
+
* @param chainSelector Chain selector
|
|
135
|
+
* @param offramp Offramp program ID
|
|
136
|
+
* @param programId Router program ID
|
|
137
|
+
* @returns [PDA, bump]
|
|
138
|
+
*/
|
|
139
|
+
export function findAllowedOfframpPDA(
|
|
140
|
+
chainSelector: bigint,
|
|
141
|
+
offramp: PublicKey,
|
|
142
|
+
programId: PublicKey,
|
|
143
|
+
): [PublicKey, number] {
|
|
144
|
+
return PublicKey.findProgramAddressSync(
|
|
145
|
+
[
|
|
146
|
+
Buffer.from(ROUTER_SEEDS.ALLOWED_OFFRAMP),
|
|
147
|
+
uint64ToLE(chainSelector),
|
|
148
|
+
offramp.toBuffer(),
|
|
149
|
+
],
|
|
150
|
+
programId,
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Finds the Token Pool Chain Config PDA for a chain selector and token mint
|
|
156
|
+
* @param chainSelector Chain selector
|
|
157
|
+
* @param tokenMint Token mint
|
|
158
|
+
* @param programId Pool program ID
|
|
159
|
+
* @returns [PDA, bump]
|
|
160
|
+
*/
|
|
161
|
+
export function findTokenPoolChainConfigPDA(
|
|
162
|
+
chainSelector: bigint,
|
|
163
|
+
tokenMint: PublicKey,
|
|
164
|
+
programId: PublicKey,
|
|
165
|
+
): [PublicKey, number] {
|
|
166
|
+
return PublicKey.findProgramAddressSync(
|
|
167
|
+
[
|
|
168
|
+
Buffer.from(ROUTER_SEEDS.TOKEN_POOL_CHAIN_CONFIG),
|
|
169
|
+
uint64ToLE(chainSelector),
|
|
170
|
+
tokenMint.toBuffer(),
|
|
171
|
+
],
|
|
172
|
+
programId,
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Finds the External Token Pools Signer PDA for a program
|
|
178
|
+
* @param programId Router program ID
|
|
179
|
+
* @returns [PDA, bump]
|
|
180
|
+
*/
|
|
181
|
+
export function findExternalTokenPoolsSignerPDA(
|
|
182
|
+
programId: PublicKey,
|
|
183
|
+
): [PublicKey, number] {
|
|
184
|
+
return PublicKey.findProgramAddressSync(
|
|
185
|
+
[Buffer.from(ROUTER_SEEDS.EXTERNAL_TOKEN_POOLS_SIGNER)],
|
|
186
|
+
programId,
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Dynamically finds the correct token pool signer PDA for a specific token by retrieving
|
|
192
|
+
* its admin registry and pool program from the lookup table.
|
|
193
|
+
*
|
|
194
|
+
* This function performs on-chain lookups to determine the exact PDA used for token transfers
|
|
195
|
+
* in the CCIP protocol, which requires both the external_token_pools_signer seed and the
|
|
196
|
+
* pool program ID from the token's lookup table.
|
|
197
|
+
*
|
|
198
|
+
* @param mint Token mint public key
|
|
199
|
+
* @param routerProgramId CCIP Router program ID
|
|
200
|
+
* @param connection Solana connection
|
|
201
|
+
* @returns Promise with [PDA, bump]
|
|
202
|
+
*/
|
|
203
|
+
export async function findDynamicTokenPoolsSignerPDA(
|
|
204
|
+
mint: PublicKey,
|
|
205
|
+
routerProgramId: PublicKey,
|
|
206
|
+
connection: Connection,
|
|
207
|
+
): Promise<[PublicKey, number]> {
|
|
208
|
+
// First find the token admin registry PDA
|
|
209
|
+
const [tokenAdminRegistryPDA] = findTokenAdminRegistryPDA(
|
|
210
|
+
mint,
|
|
211
|
+
routerProgramId,
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// Fetch the token admin registry account
|
|
215
|
+
const tokenAdminRegistryAccount = await connection.getAccountInfo(
|
|
216
|
+
tokenAdminRegistryPDA,
|
|
217
|
+
);
|
|
218
|
+
if (!tokenAdminRegistryAccount) {
|
|
219
|
+
throw new Error(
|
|
220
|
+
`Token admin registry not found for mint: ${mint.toString()}`,
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Decode the token admin registry to get the lookup table
|
|
225
|
+
const tokenRegistry = tokenAdminRegistry.decode(
|
|
226
|
+
tokenAdminRegistryAccount.data,
|
|
227
|
+
);
|
|
228
|
+
const lookupTableAddress = tokenRegistry.lookupTable;
|
|
229
|
+
|
|
230
|
+
// Fetch the lookup table
|
|
231
|
+
const { value: lookupTableAccount } = await connection.getAddressLookupTable(
|
|
232
|
+
lookupTableAddress,
|
|
233
|
+
);
|
|
234
|
+
if (!lookupTableAccount) {
|
|
235
|
+
throw new Error(`Lookup table not found: ${lookupTableAddress.toString()}`);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Get the addresses from the lookup table
|
|
239
|
+
const lookupTableAddresses = lookupTableAccount.state.addresses;
|
|
240
|
+
|
|
241
|
+
// The pool program is at index 2 in the lookup table
|
|
242
|
+
if (lookupTableAddresses.length <= 2) {
|
|
243
|
+
throw new Error(
|
|
244
|
+
"Lookup table doesn't have enough entries to determine pool program",
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Extract the pool program from the lookup table (index 2)
|
|
249
|
+
const poolProgram = lookupTableAddresses[2];
|
|
250
|
+
|
|
251
|
+
// Now create the correct PDA using both the external_token_pools_signer seed and the pool program
|
|
252
|
+
return PublicKey.findProgramAddressSync(
|
|
253
|
+
[
|
|
254
|
+
Buffer.from(ROUTER_SEEDS.EXTERNAL_TOKEN_POOLS_SIGNER),
|
|
255
|
+
poolProgram.toBuffer(),
|
|
256
|
+
],
|
|
257
|
+
routerProgramId,
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Finds the External Execution Config PDA for a program
|
|
263
|
+
* @param programId Router program ID
|
|
264
|
+
* @returns [PDA, bump]
|
|
265
|
+
*/
|
|
266
|
+
export function findExternalExecutionConfigPDA(
|
|
267
|
+
programId: PublicKey,
|
|
268
|
+
): [PublicKey, number] {
|
|
269
|
+
return PublicKey.findProgramAddressSync(
|
|
270
|
+
[Buffer.from(ROUTER_SEEDS.EXTERNAL_EXECUTION_CONFIG)],
|
|
271
|
+
programId,
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Finds the correct token pool signer PDA using the CCIPAccountReader
|
|
277
|
+
*
|
|
278
|
+
* This version uses the CCIPAccountReader which already has methods to retrieve
|
|
279
|
+
* token admin registry accounts, making the process more reliable and consistent
|
|
280
|
+
* with the rest of the SDK.
|
|
281
|
+
*
|
|
282
|
+
* @param mint Token mint public key
|
|
283
|
+
* @param routerProgramId CCIP Router program ID
|
|
284
|
+
* @param accountReader CCIPAccountReader instance
|
|
285
|
+
* @param connection Solana connection
|
|
286
|
+
* @returns Promise with [PDA, bump]
|
|
287
|
+
*/
|
|
288
|
+
export async function findTokenPoolsSignerWithAccountReader(
|
|
289
|
+
mint: PublicKey,
|
|
290
|
+
routerProgramId: PublicKey,
|
|
291
|
+
accountReader: import("../../core/client/accounts").CCIPAccountReader,
|
|
292
|
+
connection: Connection,
|
|
293
|
+
): Promise<[PublicKey, number]> {
|
|
294
|
+
// Use the account reader to get the token admin registry
|
|
295
|
+
const tokenRegistry = await accountReader.getTokenAdminRegistry(mint);
|
|
296
|
+
|
|
297
|
+
// Fetch the lookup table
|
|
298
|
+
const { value: lookupTableAccount } = await connection.getAddressLookupTable(
|
|
299
|
+
tokenRegistry.lookupTable,
|
|
300
|
+
);
|
|
301
|
+
if (!lookupTableAccount) {
|
|
302
|
+
throw new Error(
|
|
303
|
+
`Lookup table not found: ${tokenRegistry.lookupTable.toString()}`,
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Get the addresses from the lookup table
|
|
308
|
+
const lookupTableAddresses = lookupTableAccount.state.addresses;
|
|
309
|
+
|
|
310
|
+
// The pool program is at index 2 in the lookup table
|
|
311
|
+
if (lookupTableAddresses.length <= 2) {
|
|
312
|
+
throw new Error(
|
|
313
|
+
"Lookup table doesn't have enough entries to determine pool program",
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Extract the pool program from the lookup table (index 2)
|
|
318
|
+
const poolProgram = lookupTableAddresses[2];
|
|
319
|
+
|
|
320
|
+
// Now create the correct PDA using both the external_token_pools_signer seed and the pool program
|
|
321
|
+
return PublicKey.findProgramAddressSync(
|
|
322
|
+
[
|
|
323
|
+
Buffer.from(ROUTER_SEEDS.EXTERNAL_TOKEN_POOLS_SIGNER),
|
|
324
|
+
poolProgram.toBuffer(),
|
|
325
|
+
],
|
|
326
|
+
routerProgramId,
|
|
327
|
+
);
|
|
328
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import { uint64ToLE } from "./common";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Token Pool PDA utilities
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Token Pool seed constants
|
|
9
|
+
export const TOKEN_POOL_STATE_SEED = "state";
|
|
10
|
+
export const TOKEN_POOL_CHAIN_CONFIG_SEED = "chain_config";
|
|
11
|
+
export const TOKEN_POOL_POOL_SIGNER_SEED = "pool_signer";
|
|
12
|
+
export const TOKEN_POOL_RATE_LIMIT_STATE_SEED = "rate_limit_state";
|
|
13
|
+
export const TOKEN_POOL_CHAIN_RATE_LIMIT_SEED = "chain_rate_limit";
|
|
14
|
+
export const TOKEN_POOL_BURN_TRACKING_SEED = "burn_tracking";
|
|
15
|
+
export const TOKEN_POOL_MINT_TRACKING_SEED = "mint_tracking";
|
|
16
|
+
|
|
17
|
+
// Solana system program IDs
|
|
18
|
+
// Use the official BPF Loader Upgradeable Program ID
|
|
19
|
+
// This is hardcoded because @solana/web3.js does not export it directly
|
|
20
|
+
export const BPF_LOADER_UPGRADEABLE_PROGRAM_ID = new PublicKey(
|
|
21
|
+
"BPFLoaderUpgradeab1e11111111111111111111111"
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Finds the State PDA for the burn-mint pool (main configuration)
|
|
26
|
+
* @param mint Token mint
|
|
27
|
+
* @param programId Burn-mint pool program ID
|
|
28
|
+
* @returns [PDA, bump]
|
|
29
|
+
*/
|
|
30
|
+
export function findBurnMintPoolConfigPDA(
|
|
31
|
+
mint: PublicKey,
|
|
32
|
+
programId: PublicKey
|
|
33
|
+
): [PublicKey, number] {
|
|
34
|
+
return PublicKey.findProgramAddressSync(
|
|
35
|
+
[Buffer.from(TOKEN_POOL_STATE_SEED), mint.toBuffer()],
|
|
36
|
+
programId
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Finds the Chain Config PDA for a chain selector and token mint
|
|
42
|
+
* @param chainSelector Chain selector
|
|
43
|
+
* @param tokenMint Token mint
|
|
44
|
+
* @param programId Burn-mint pool program ID
|
|
45
|
+
* @returns [PDA, bump]
|
|
46
|
+
*/
|
|
47
|
+
export function findBurnMintPoolChainConfigPDA(
|
|
48
|
+
chainSelector: bigint,
|
|
49
|
+
tokenMint: PublicKey,
|
|
50
|
+
programId: PublicKey
|
|
51
|
+
): [PublicKey, number] {
|
|
52
|
+
return PublicKey.findProgramAddressSync(
|
|
53
|
+
[
|
|
54
|
+
Buffer.from(TOKEN_POOL_CHAIN_CONFIG_SEED),
|
|
55
|
+
uint64ToLE(chainSelector),
|
|
56
|
+
tokenMint.toBuffer(),
|
|
57
|
+
],
|
|
58
|
+
programId
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Finds the Program Data PDA for the burn-mint pool program
|
|
64
|
+
* @param programId Burn-mint pool program ID
|
|
65
|
+
* @returns [PDA, bump]
|
|
66
|
+
*/
|
|
67
|
+
export function findProgramDataPDA(programId: PublicKey): [PublicKey, number] {
|
|
68
|
+
return PublicKey.findProgramAddressSync(
|
|
69
|
+
[programId.toBuffer()],
|
|
70
|
+
BPF_LOADER_UPGRADEABLE_PROGRAM_ID
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Finds the Rate Limit State PDA for a token mint
|
|
76
|
+
* This is used for global rate limiting
|
|
77
|
+
* @param tokenMint Token mint
|
|
78
|
+
* @param programId Burn-mint pool program ID
|
|
79
|
+
* @returns [PDA, bump]
|
|
80
|
+
*/
|
|
81
|
+
export function findRateLimitStatePDA(
|
|
82
|
+
tokenMint: PublicKey,
|
|
83
|
+
programId: PublicKey
|
|
84
|
+
): [PublicKey, number] {
|
|
85
|
+
return PublicKey.findProgramAddressSync(
|
|
86
|
+
[Buffer.from(TOKEN_POOL_RATE_LIMIT_STATE_SEED), tokenMint.toBuffer()],
|
|
87
|
+
programId
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Finds the Chain Rate Limit PDA for a chain selector and token mint
|
|
93
|
+
* This is used for per-chain rate limiting
|
|
94
|
+
* @param chainSelector Chain selector
|
|
95
|
+
* @param tokenMint Token mint
|
|
96
|
+
* @param programId Burn-mint pool program ID
|
|
97
|
+
* @returns [PDA, bump]
|
|
98
|
+
*/
|
|
99
|
+
export function findChainRateLimitPDA(
|
|
100
|
+
chainSelector: bigint,
|
|
101
|
+
tokenMint: PublicKey,
|
|
102
|
+
programId: PublicKey
|
|
103
|
+
): [PublicKey, number] {
|
|
104
|
+
return PublicKey.findProgramAddressSync(
|
|
105
|
+
[
|
|
106
|
+
Buffer.from(TOKEN_POOL_CHAIN_RATE_LIMIT_SEED),
|
|
107
|
+
uint64ToLE(chainSelector),
|
|
108
|
+
tokenMint.toBuffer(),
|
|
109
|
+
],
|
|
110
|
+
programId
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Finds the Pool Signer PDA for a mint
|
|
116
|
+
* Used as the authority for token accounts
|
|
117
|
+
* @param mint Token mint
|
|
118
|
+
* @param programId Burn-mint pool program ID
|
|
119
|
+
* @returns [PDA, bump]
|
|
120
|
+
*/
|
|
121
|
+
export function findPoolSignerPDA(
|
|
122
|
+
mint: PublicKey,
|
|
123
|
+
programId: PublicKey
|
|
124
|
+
): [PublicKey, number] {
|
|
125
|
+
return PublicKey.findProgramAddressSync(
|
|
126
|
+
[Buffer.from(TOKEN_POOL_POOL_SIGNER_SEED), mint.toBuffer()],
|
|
127
|
+
programId
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Finds the Burn Tracking PDA for a message ID
|
|
133
|
+
* @param messageId Message ID as byte array
|
|
134
|
+
* @param programId Burn-mint pool program ID
|
|
135
|
+
* @returns [PDA, bump]
|
|
136
|
+
*/
|
|
137
|
+
export function findBurnTrackingPDA(
|
|
138
|
+
messageId: Uint8Array,
|
|
139
|
+
programId: PublicKey
|
|
140
|
+
): [PublicKey, number] {
|
|
141
|
+
return PublicKey.findProgramAddressSync(
|
|
142
|
+
[Buffer.from(TOKEN_POOL_BURN_TRACKING_SEED), Buffer.from(messageId)],
|
|
143
|
+
programId
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Finds the Mint Tracking PDA for a message ID
|
|
149
|
+
* @param messageId Message ID as byte array
|
|
150
|
+
* @param programId Burn-mint pool program ID
|
|
151
|
+
* @returns [PDA, bump]
|
|
152
|
+
*/
|
|
153
|
+
export function findMintTrackingPDA(
|
|
154
|
+
messageId: Uint8Array,
|
|
155
|
+
programId: PublicKey
|
|
156
|
+
): [PublicKey, number] {
|
|
157
|
+
return PublicKey.findProgramAddressSync(
|
|
158
|
+
[Buffer.from(TOKEN_POOL_MINT_TRACKING_SEED), Buffer.from(messageId)],
|
|
159
|
+
programId
|
|
160
|
+
);
|
|
161
|
+
}
|