@fogo/sessions-sdk 0.1.8 → 0.1.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/cjs/connection.d.ts +10 -10
- package/cjs/connection.js +22 -22
- package/cjs/context.d.ts +4 -4
- package/cjs/context.js +4 -4
- package/cjs/crypto.js +1 -1
- package/cjs/index.d.ts +220 -2030
- package/cjs/index.js +186 -75
- package/cjs/instructions.js +9 -9
- package/esm/connection.d.ts +10 -10
- package/esm/connection.js +23 -23
- package/esm/context.d.ts +4 -4
- package/esm/context.js +4 -4
- package/esm/crypto.js +1 -1
- package/esm/index.d.ts +220 -2030
- package/esm/index.js +155 -77
- package/esm/instructions.js +9 -9
- package/package.json +41 -40
package/esm/index.js
CHANGED
|
@@ -3,17 +3,18 @@ import { DomainRegistryIdl, IntentTransferIdl, IntentTransferProgram, SessionMan
|
|
|
3
3
|
import { findMetadataPda, safeFetchMetadata, } from "@metaplex-foundation/mpl-token-metadata";
|
|
4
4
|
import { publicKey as metaplexPublicKey } from "@metaplex-foundation/umi";
|
|
5
5
|
import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
|
|
6
|
-
import { sha256 } from "@noble/hashes/sha2";
|
|
6
|
+
import { sha256 } from "@noble/hashes/sha2.js";
|
|
7
7
|
import { fromLegacyPublicKey } from "@solana/compat";
|
|
8
|
-
import { generateKeyPair, getAddressFromPublicKey, getProgramDerivedAddress, } from "@solana/kit";
|
|
8
|
+
import { generateKeyPair, getAddressFromPublicKey, getOffchainMessageDecoder, getProgramDerivedAddress, } from "@solana/kit";
|
|
9
9
|
import { getAssociatedTokenAddressSync, getMint } from "@solana/spl-token";
|
|
10
|
-
import { ComputeBudgetProgram, Ed25519Program, Keypair, PublicKey, } from "@solana/web3.js";
|
|
11
|
-
import {
|
|
10
|
+
import { ComputeBudgetProgram, Ed25519Program, Keypair, PublicKey, TransactionInstruction, } from "@solana/web3.js";
|
|
11
|
+
import { Wormhole, wormhole } from "@wormhole-foundation/sdk";
|
|
12
12
|
import solanaSdk from "@wormhole-foundation/sdk/solana";
|
|
13
13
|
import { contracts } from "@wormhole-foundation/sdk-base";
|
|
14
|
+
import * as routes from "@wormhole-foundation/sdk-connect/routes";
|
|
14
15
|
import { nttExecutorRoute } from "@wormhole-foundation/sdk-route-ntt";
|
|
15
16
|
import { utils } from "@wormhole-foundation/sdk-solana-core";
|
|
16
|
-
import { NTT } from "@wormhole-foundation/sdk-solana-ntt";
|
|
17
|
+
import { NTT, register as registerNtt, } from "@wormhole-foundation/sdk-solana-ntt";
|
|
17
18
|
import BN from "bn.js";
|
|
18
19
|
import bs58 from "bs58";
|
|
19
20
|
import { z } from "zod";
|
|
@@ -23,6 +24,7 @@ import { importKey, signMessageWithKey, verifyMessageWithKey, } from "./crypto.j
|
|
|
23
24
|
import { createSessionUnwrapInstruction, createSessionWrapInstructions, createSystemProgramSessionWrapInstruction, } from "./instructions.js";
|
|
24
25
|
import { USDC_DECIMALS, USDC_MINT } from "./mints.js";
|
|
25
26
|
import { Network } from "./network.js";
|
|
27
|
+
registerNtt();
|
|
26
28
|
export { createSessionConnection, TransactionResultType, } from "./connection.js";
|
|
27
29
|
export { createSessionContext, } from "./context.js";
|
|
28
30
|
export { createPaymasterFeeInstruction, createSessionUnwrapInstruction, createSessionWrapInstructions, createSystemProgramSessionWrapInstruction, } from "./instructions.js";
|
|
@@ -67,9 +69,9 @@ export const establishSession = async (options) => {
|
|
|
67
69
|
};
|
|
68
70
|
const sendSessionEstablishTransaction = async (options, sessionKey, instructions, sessionEstablishmentLookupTable) => {
|
|
69
71
|
const result = await options.context.sendTransaction(sessionKey, instructions, options.walletPublicKey, {
|
|
70
|
-
variation: "Session Establishment",
|
|
71
72
|
addressLookupTable: sessionEstablishmentLookupTable ??
|
|
72
73
|
SESSION_ESTABLISHMENT_LOOKUP_TABLE_ADDRESS[options.context.network],
|
|
74
|
+
variation: "Session Establishment",
|
|
73
75
|
});
|
|
74
76
|
switch (result.type) {
|
|
75
77
|
case TransactionResultType.Success: {
|
|
@@ -92,8 +94,8 @@ export const revokeSession = async (options) => {
|
|
|
92
94
|
const instruction = await new SessionManagerProgram(new AnchorProvider(options.context.connection, {}, {})).methods
|
|
93
95
|
.revokeSession()
|
|
94
96
|
.accounts({
|
|
95
|
-
sponsor: options.session.sessionInfo.sponsor,
|
|
96
97
|
session: options.session.sessionPublicKey,
|
|
98
|
+
sponsor: options.session.sessionInfo.sponsor,
|
|
97
99
|
})
|
|
98
100
|
.instruction();
|
|
99
101
|
return options.context.sendTransaction(options.session.sessionKey, [instruction], options.session.walletPublicKey, {
|
|
@@ -143,17 +145,17 @@ const createSession = async (context, walletPublicKey, sessionKey) => {
|
|
|
143
145
|
!authorizedProgramsMatchDomainRegistry(sessionInfo.authorizedPrograms, domainRegistryAuthorizedPrograms)
|
|
144
146
|
? undefined
|
|
145
147
|
: {
|
|
146
|
-
sessionPublicKey,
|
|
147
|
-
walletPublicKey,
|
|
148
|
-
sessionKey,
|
|
149
|
-
payer: context.payer,
|
|
150
|
-
getSystemProgramSessionWrapInstruction: (amount) => createSystemProgramSessionWrapInstruction(sessionPublicKey, walletPublicKey, amount),
|
|
151
|
-
getSessionWrapInstructions: (amount) => createSessionWrapInstructions(sessionPublicKey, walletPublicKey, amount),
|
|
152
148
|
getSessionUnwrapInstructions: () => [
|
|
153
149
|
createSessionUnwrapInstruction(sessionPublicKey, walletPublicKey),
|
|
154
150
|
],
|
|
151
|
+
getSessionWrapInstructions: (amount) => createSessionWrapInstructions(sessionPublicKey, walletPublicKey, amount),
|
|
152
|
+
getSystemProgramSessionWrapInstruction: (amount) => createSystemProgramSessionWrapInstruction(sessionPublicKey, walletPublicKey, amount),
|
|
153
|
+
payer: context.payer,
|
|
155
154
|
sendTransaction: (instructions, extraConfig) => context.sendTransaction(sessionKey, instructions, walletPublicKey, extraConfig),
|
|
156
155
|
sessionInfo,
|
|
156
|
+
sessionKey,
|
|
157
|
+
sessionPublicKey,
|
|
158
|
+
walletPublicKey,
|
|
157
159
|
};
|
|
158
160
|
};
|
|
159
161
|
const authorizedTokensSchema = z.union([
|
|
@@ -165,9 +167,9 @@ const authorizedTokensSchema = z.union([
|
|
|
165
167
|
z.object({ All: z.object({}) }),
|
|
166
168
|
]);
|
|
167
169
|
const revokedSessionInfoSchema = z.object({
|
|
168
|
-
user: z.instanceof(PublicKey),
|
|
169
|
-
expiration: z.instanceof(BN),
|
|
170
170
|
authorized_tokens_with_mints: authorizedTokensSchema,
|
|
171
|
+
expiration: z.instanceof(BN),
|
|
172
|
+
user: z.instanceof(PublicKey),
|
|
171
173
|
});
|
|
172
174
|
const activeSessionInfoSchema = z.object({
|
|
173
175
|
authorized_programs: z.union([
|
|
@@ -199,6 +201,7 @@ const activeSessionInfoSchema = z.object({
|
|
|
199
201
|
});
|
|
200
202
|
const sessionInfoSchema = z
|
|
201
203
|
.object({
|
|
204
|
+
major: z.number(),
|
|
202
205
|
session_info: z.union([
|
|
203
206
|
z.object({
|
|
204
207
|
V1: z.object({
|
|
@@ -292,8 +295,8 @@ const sessionInfoSchema = z
|
|
|
292
295
|
z.object({
|
|
293
296
|
Active: z.object({
|
|
294
297
|
"0": z.object({
|
|
295
|
-
domain_hash: z.array(z.number()).length(32),
|
|
296
298
|
active_session_info: activeSessionInfoSchema,
|
|
299
|
+
domain_hash: z.array(z.number()).length(32),
|
|
297
300
|
}),
|
|
298
301
|
}),
|
|
299
302
|
}),
|
|
@@ -301,7 +304,6 @@ const sessionInfoSchema = z
|
|
|
301
304
|
}),
|
|
302
305
|
}),
|
|
303
306
|
]),
|
|
304
|
-
major: z.number(),
|
|
305
307
|
sponsor: z.instanceof(PublicKey),
|
|
306
308
|
})
|
|
307
309
|
.transform(({ session_info, major, sponsor }) => {
|
|
@@ -340,8 +342,8 @@ const sessionInfoSchema = z
|
|
|
340
342
|
extra: activeSessionInfo.extra[0],
|
|
341
343
|
major: major,
|
|
342
344
|
minor: minor,
|
|
343
|
-
user: activeSessionInfo.user,
|
|
344
345
|
sponsor,
|
|
346
|
+
user: activeSessionInfo.user,
|
|
345
347
|
};
|
|
346
348
|
});
|
|
347
349
|
export var AuthorizedProgramsType;
|
|
@@ -352,8 +354,8 @@ export var AuthorizedProgramsType;
|
|
|
352
354
|
const AuthorizedPrograms = {
|
|
353
355
|
All: () => ({ type: AuthorizedProgramsType.All }),
|
|
354
356
|
Specific: (programs) => ({
|
|
355
|
-
type: AuthorizedProgramsType.Specific,
|
|
356
357
|
programs,
|
|
358
|
+
type: AuthorizedProgramsType.Specific,
|
|
357
359
|
}),
|
|
358
360
|
};
|
|
359
361
|
export var AuthorizedTokens;
|
|
@@ -367,13 +369,13 @@ var SymbolOrMintType;
|
|
|
367
369
|
SymbolOrMintType[SymbolOrMintType["Mint"] = 1] = "Mint";
|
|
368
370
|
})(SymbolOrMintType || (SymbolOrMintType = {}));
|
|
369
371
|
const SymbolOrMint = {
|
|
370
|
-
Symbol: (symbol) => ({
|
|
371
|
-
type: SymbolOrMintType.Symbol,
|
|
372
|
-
symbol,
|
|
373
|
-
}),
|
|
374
372
|
Mint: (mint) => ({
|
|
375
|
-
type: SymbolOrMintType.Mint,
|
|
376
373
|
mint,
|
|
374
|
+
type: SymbolOrMintType.Mint,
|
|
375
|
+
}),
|
|
376
|
+
Symbol: (symbol) => ({
|
|
377
|
+
symbol,
|
|
378
|
+
type: SymbolOrMintType.Symbol,
|
|
377
379
|
}),
|
|
378
380
|
};
|
|
379
381
|
const getTokenInfo = (context, limits) => {
|
|
@@ -386,17 +388,19 @@ const getTokenInfo = (context, limits) => {
|
|
|
386
388
|
safeFetchMetadata(umi, metadataAddress),
|
|
387
389
|
]);
|
|
388
390
|
return {
|
|
391
|
+
amount,
|
|
392
|
+
decimals: mintInfo.decimals,
|
|
393
|
+
metadataAddress: new PublicKey(metadataAddress),
|
|
394
|
+
mint,
|
|
389
395
|
symbolOrMint: metadata?.symbol
|
|
390
396
|
? SymbolOrMint.Symbol(metadata.symbol)
|
|
391
397
|
: SymbolOrMint.Mint(mint),
|
|
392
|
-
metadataAddress: new PublicKey(metadataAddress),
|
|
393
|
-
amount,
|
|
394
|
-
mint,
|
|
395
|
-
decimals: mintInfo.decimals,
|
|
396
398
|
};
|
|
397
399
|
}));
|
|
398
400
|
};
|
|
399
|
-
const buildStartSessionIntentInstruction = async (options, sessionKey, tokens) => buildIntentInstruction(options, MESSAGE_HEADER,
|
|
401
|
+
const buildStartSessionIntentInstruction = async (options, sessionKey, tokens) => buildIntentInstruction(options, MESSAGE_HEADER,
|
|
402
|
+
// biome-ignore assist/source/useSortedKeys: The sort order is important here
|
|
403
|
+
{
|
|
400
404
|
version: `${CURRENT_MAJOR}.${CURRENT_MINOR}`,
|
|
401
405
|
chain_id: options.context.chainId,
|
|
402
406
|
domain: options.context.domain,
|
|
@@ -407,12 +411,80 @@ const buildStartSessionIntentInstruction = async (options, sessionKey, tokens) =
|
|
|
407
411
|
const buildIntentInstruction = async (options, header, body, extra) => {
|
|
408
412
|
const message = new TextEncoder().encode([header, serializeKV(body), extra && serializeExtra(extra)].join("\n"));
|
|
409
413
|
const { signature, signedMessage } = await options.signMessage(message);
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
+
const publicKey = options.walletPublicKey.toBytes();
|
|
415
|
+
const publicKeyOffsetInMessage = getOffchainMessagePublicKeyOffset(signedMessage, options.walletPublicKey);
|
|
416
|
+
if (publicKeyOffsetInMessage !== undefined) {
|
|
417
|
+
return buildEd25519InstructionWithOffsets({
|
|
418
|
+
message: signedMessage,
|
|
419
|
+
publicKeyOffsetInMessage,
|
|
420
|
+
signature,
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
return Ed25519Program.createInstructionWithPublicKey({
|
|
425
|
+
message: signedMessage,
|
|
426
|
+
publicKey,
|
|
427
|
+
signature,
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
const ED25519_HEADER_LEN = 16;
|
|
432
|
+
const ED25519_PUBLIC_KEY_LEN = 32;
|
|
433
|
+
const ED25519_SIGNATURE_LEN = 64;
|
|
434
|
+
const ED25519_CURRENT_INSTRUCTION_INDEX = 0xff_ff;
|
|
435
|
+
const buildEd25519InstructionWithOffsets = (params) => {
|
|
436
|
+
const { signature, message, publicKeyOffsetInMessage } = params;
|
|
437
|
+
if (signature.length !== ED25519_SIGNATURE_LEN) {
|
|
438
|
+
throw new Error(`Signature must be ${ED25519_SIGNATURE_LEN} bytes but received ${signature.length} bytes`);
|
|
439
|
+
}
|
|
440
|
+
if (publicKeyOffsetInMessage < 0 ||
|
|
441
|
+
publicKeyOffsetInMessage + ED25519_PUBLIC_KEY_LEN > message.length) {
|
|
442
|
+
throw new Error("Public key offset is out of bounds of signed message");
|
|
443
|
+
}
|
|
444
|
+
const signatureOffset = ED25519_HEADER_LEN;
|
|
445
|
+
const messageDataOffset = signatureOffset + signature.length;
|
|
446
|
+
const publicKeyOffsetInInstruction = messageDataOffset + publicKeyOffsetInMessage;
|
|
447
|
+
const instructionData = new Uint8Array(ED25519_HEADER_LEN + ED25519_SIGNATURE_LEN + message.length);
|
|
448
|
+
const view = new DataView(instructionData.buffer);
|
|
449
|
+
view.setUint8(0, 1); // num_signatures
|
|
450
|
+
view.setUint8(1, 0); // padding
|
|
451
|
+
view.setUint16(2, signatureOffset, true);
|
|
452
|
+
view.setUint16(4, ED25519_CURRENT_INSTRUCTION_INDEX, true);
|
|
453
|
+
view.setUint16(6, publicKeyOffsetInInstruction, true);
|
|
454
|
+
view.setUint16(8, ED25519_CURRENT_INSTRUCTION_INDEX, true);
|
|
455
|
+
view.setUint16(10, messageDataOffset, true);
|
|
456
|
+
view.setUint16(12, message.length, true);
|
|
457
|
+
view.setUint16(14, ED25519_CURRENT_INSTRUCTION_INDEX, true);
|
|
458
|
+
instructionData.set(signature, signatureOffset);
|
|
459
|
+
instructionData.set(message, messageDataOffset);
|
|
460
|
+
return new TransactionInstruction({
|
|
461
|
+
data: Buffer.from(instructionData),
|
|
462
|
+
keys: [],
|
|
463
|
+
programId: Ed25519Program.programId,
|
|
414
464
|
});
|
|
415
465
|
};
|
|
466
|
+
const OFFCHAIN_SIGNING_DOMAIN_LEN = 16;
|
|
467
|
+
const OFFCHAIN_V0_SIGNER_LIST_OFFSET = OFFCHAIN_SIGNING_DOMAIN_LEN + 1 + 32 + 1 + 1;
|
|
468
|
+
const OFFCHAIN_V1_SIGNER_LIST_OFFSET = OFFCHAIN_SIGNING_DOMAIN_LEN + 1 + 1;
|
|
469
|
+
const getOffchainMessagePublicKeyOffset = (signedMessage, publicKey) => {
|
|
470
|
+
const address = publicKey.toBase58();
|
|
471
|
+
try {
|
|
472
|
+
const message = getOffchainMessageDecoder().decode(signedMessage);
|
|
473
|
+
const index = message.requiredSignatories.findIndex((signer) => signer.address === address);
|
|
474
|
+
if (index !== -1) {
|
|
475
|
+
const baseOffset = message.version === 1
|
|
476
|
+
? OFFCHAIN_V1_SIGNER_LIST_OFFSET
|
|
477
|
+
: OFFCHAIN_V0_SIGNER_LIST_OFFSET;
|
|
478
|
+
return baseOffset + index * ED25519_PUBLIC_KEY_LEN;
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
return undefined;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
catch {
|
|
485
|
+
return undefined;
|
|
486
|
+
}
|
|
487
|
+
};
|
|
416
488
|
const serializeExtra = (extra) => {
|
|
417
489
|
for (const [key, value] of Object.entries(extra)) {
|
|
418
490
|
if (!/^[a-z]+(_[a-z0-9]+)*$/.test(key)) {
|
|
@@ -454,7 +526,7 @@ const amountToString = (amount, decimals) => {
|
|
|
454
526
|
].join("");
|
|
455
527
|
};
|
|
456
528
|
export const getDomainRecordAddress = (domain) => {
|
|
457
|
-
const hash = sha256(domain);
|
|
529
|
+
const hash = sha256(new TextEncoder().encode(domain));
|
|
458
530
|
return PublicKey.findProgramAddressSync([Buffer.from("domain-record"), hash], new PublicKey(DomainRegistryIdl.address))[0];
|
|
459
531
|
};
|
|
460
532
|
const BRIDGING_ADDRESS_LOOKUP_TABLE = {
|
|
@@ -471,30 +543,30 @@ const buildStartSessionInstruction = async (options, sessionKey, tokens) => {
|
|
|
471
543
|
const instruction = new SessionManagerProgram(new AnchorProvider(options.context.connection, {}, {})).methods
|
|
472
544
|
.startSession()
|
|
473
545
|
.accounts({
|
|
474
|
-
sponsor: options.context.payer,
|
|
475
|
-
session: await getAddressFromPublicKey(sessionKey.publicKey),
|
|
476
546
|
domainRegistry: getDomainRecordAddress(options.context.domain),
|
|
547
|
+
session: await getAddressFromPublicKey(sessionKey.publicKey),
|
|
548
|
+
sponsor: options.context.payer,
|
|
477
549
|
});
|
|
478
550
|
return tokens === undefined
|
|
479
551
|
? instruction.instruction()
|
|
480
552
|
: instruction
|
|
481
553
|
.remainingAccounts(tokens.flatMap(({ symbolOrMint, mint, metadataAddress }) => [
|
|
482
554
|
{
|
|
483
|
-
pubkey: getAssociatedTokenAddressSync(mint, options.walletPublicKey),
|
|
484
|
-
isWritable: true,
|
|
485
555
|
isSigner: false,
|
|
556
|
+
isWritable: true,
|
|
557
|
+
pubkey: getAssociatedTokenAddressSync(mint, options.walletPublicKey),
|
|
486
558
|
},
|
|
487
559
|
{
|
|
488
|
-
pubkey: mint,
|
|
489
|
-
isWritable: false,
|
|
490
560
|
isSigner: false,
|
|
561
|
+
isWritable: false,
|
|
562
|
+
pubkey: mint,
|
|
491
563
|
},
|
|
492
564
|
...(symbolOrMint.type === SymbolOrMintType.Symbol
|
|
493
565
|
? [
|
|
494
566
|
{
|
|
495
|
-
pubkey: metadataAddress,
|
|
496
|
-
isWritable: false,
|
|
497
567
|
isSigner: false,
|
|
568
|
+
isWritable: false,
|
|
569
|
+
pubkey: metadataAddress,
|
|
498
570
|
},
|
|
499
571
|
]
|
|
500
572
|
: []),
|
|
@@ -507,15 +579,15 @@ export var SessionResultType;
|
|
|
507
579
|
SessionResultType[SessionResultType["Failed"] = 1] = "Failed";
|
|
508
580
|
})(SessionResultType || (SessionResultType = {}));
|
|
509
581
|
const EstablishSessionResult = {
|
|
510
|
-
Success: (signature, session) => ({
|
|
511
|
-
type: SessionResultType.Success,
|
|
512
|
-
signature,
|
|
513
|
-
session,
|
|
514
|
-
}),
|
|
515
582
|
Failed: (signature, error) => ({
|
|
583
|
+
error,
|
|
584
|
+
signature,
|
|
516
585
|
type: SessionResultType.Failed,
|
|
586
|
+
}),
|
|
587
|
+
Success: (signature, session) => ({
|
|
588
|
+
session,
|
|
517
589
|
signature,
|
|
518
|
-
|
|
590
|
+
type: SessionResultType.Success,
|
|
519
591
|
}),
|
|
520
592
|
};
|
|
521
593
|
export const getTransferFee = async (context) => {
|
|
@@ -540,16 +612,16 @@ const getFee = async (context) => {
|
|
|
540
612
|
const [feeConfigPda] = PublicKey.findProgramAddressSync([Buffer.from("fee_config"), usdcMint.toBytes()], program.programId);
|
|
541
613
|
const feeConfig = await program.account.feeConfig.fetch(feeConfigPda);
|
|
542
614
|
return {
|
|
615
|
+
decimals: USDC_DECIMALS,
|
|
616
|
+
fee: {
|
|
617
|
+
bridgeTransfer: BigInt(feeConfig.bridgeTransferFee.toString()),
|
|
618
|
+
intrachainTransfer: BigInt(feeConfig.intrachainTransferFee.toString()),
|
|
619
|
+
},
|
|
543
620
|
metadata: findMetadataPda(umi, {
|
|
544
621
|
mint: metaplexPublicKey(usdcMintAddress),
|
|
545
622
|
})[0],
|
|
546
623
|
mint: usdcMint,
|
|
547
624
|
symbolOrMint: "USDC.s",
|
|
548
|
-
decimals: USDC_DECIMALS,
|
|
549
|
-
fee: {
|
|
550
|
-
intrachainTransfer: BigInt(feeConfig.intrachainTransferFee.toString()),
|
|
551
|
-
bridgeTransfer: BigInt(feeConfig.bridgeTransferFee.toString()),
|
|
552
|
-
},
|
|
553
625
|
};
|
|
554
626
|
};
|
|
555
627
|
const TRANSFER_MESSAGE_HEADER = `Fogo Transfer:
|
|
@@ -572,17 +644,17 @@ export const sendTransfer = async (options) => {
|
|
|
572
644
|
feeMetadata: options.feeConfig.metadata,
|
|
573
645
|
feeMint: options.feeConfig.mint,
|
|
574
646
|
feeSource: getAssociatedTokenAddressSync(options.feeConfig.mint, options.walletPublicKey),
|
|
575
|
-
mint: options.mint,
|
|
576
|
-
source: sourceAta,
|
|
577
|
-
sponsor: options.context.internalPayer,
|
|
578
647
|
metadata:
|
|
579
648
|
// eslint-disable-next-line unicorn/no-null
|
|
580
649
|
symbol === undefined ? null : new PublicKey(metadataAddress),
|
|
650
|
+
mint: options.mint,
|
|
651
|
+
source: sourceAta,
|
|
652
|
+
sponsor: options.context.internalPayer,
|
|
581
653
|
})
|
|
582
654
|
.instruction(),
|
|
583
655
|
], options.walletPublicKey, {
|
|
584
|
-
variation: "Intent Transfer",
|
|
585
656
|
paymasterDomain: SESSIONS_INTERNAL_PAYMASTER_DOMAIN,
|
|
657
|
+
variation: "Intent Transfer",
|
|
586
658
|
});
|
|
587
659
|
};
|
|
588
660
|
const buildTransferIntentInstruction = async (program, options, symbol, feeToken, feeAmount) => {
|
|
@@ -590,7 +662,9 @@ const buildTransferIntentInstruction = async (program, options, symbol, feeToken
|
|
|
590
662
|
getNonce(program, options.walletPublicKey, NonceType.Transfer),
|
|
591
663
|
getMint(options.context.connection, options.mint),
|
|
592
664
|
]);
|
|
593
|
-
return buildIntentInstruction(options, TRANSFER_MESSAGE_HEADER,
|
|
665
|
+
return buildIntentInstruction(options, TRANSFER_MESSAGE_HEADER,
|
|
666
|
+
// biome-ignore assist/source/useSortedKeys: The sort order is important here
|
|
667
|
+
{
|
|
594
668
|
version: `${CURRENT_INTENT_TRANSFER_MAJOR}.${CURRENT_INTENT_TRANSFER_MINOR}`,
|
|
595
669
|
chain_id: options.context.chainId,
|
|
596
670
|
token: symbol ?? options.mint.toBase58(),
|
|
@@ -608,24 +682,26 @@ export const sendNativeTransfer = async (options) => {
|
|
|
608
682
|
await program.methods
|
|
609
683
|
.sendNative()
|
|
610
684
|
.accounts({
|
|
685
|
+
destination: options.recipient,
|
|
686
|
+
feeDestination: IntentTransferIdl.address,
|
|
611
687
|
feeMetadata: options.feeConfig.metadata,
|
|
612
688
|
feeMint: options.feeConfig.mint,
|
|
613
689
|
feeSource: getAssociatedTokenAddressSync(options.feeConfig.mint, options.walletPublicKey),
|
|
614
|
-
feeDestination: IntentTransferIdl.address,
|
|
615
690
|
source: options.walletPublicKey,
|
|
616
|
-
destination: options.recipient,
|
|
617
691
|
sponsor: options.context.internalPayer,
|
|
618
692
|
})
|
|
619
693
|
.instruction(),
|
|
620
694
|
], options.walletPublicKey, {
|
|
621
|
-
variation: "Intent Transfer",
|
|
622
695
|
paymasterDomain: SESSIONS_INTERNAL_PAYMASTER_DOMAIN,
|
|
696
|
+
variation: "Intent Transfer",
|
|
623
697
|
});
|
|
624
698
|
};
|
|
625
699
|
const FOGO_DECIMALS = 9;
|
|
626
700
|
const buildNativeTransferIntentInstruction = async (program, options, feeToken, feeAmount) => {
|
|
627
701
|
const nonce = await getNonce(program, options.walletPublicKey, NonceType.Transfer);
|
|
628
|
-
return buildIntentInstruction(options, TRANSFER_MESSAGE_HEADER,
|
|
702
|
+
return buildIntentInstruction(options, TRANSFER_MESSAGE_HEADER,
|
|
703
|
+
// biome-ignore assist/source/useSortedKeys: The sort order is important here
|
|
704
|
+
{
|
|
629
705
|
version: `${CURRENT_INTENT_TRANSFER_MAJOR}.${CURRENT_INTENT_TRANSFER_MINOR}`,
|
|
630
706
|
chain_id: options.context.chainId,
|
|
631
707
|
token: "FOGO",
|
|
@@ -663,17 +739,17 @@ export const bridgeOut = async (options) => {
|
|
|
663
739
|
signedQuoteBytes: [...quote.signedQuote],
|
|
664
740
|
})
|
|
665
741
|
.accounts({
|
|
666
|
-
|
|
667
|
-
|
|
742
|
+
feeMetadata: options.feeConfig.metadata,
|
|
743
|
+
feeMint: options.feeConfig.mint,
|
|
744
|
+
feeSource: getAssociatedTokenAddressSync(options.feeConfig.mint, options.walletPublicKey),
|
|
668
745
|
metadata: metadata?.symbol === undefined
|
|
669
746
|
? // eslint-disable-next-line unicorn/no-null
|
|
670
747
|
null
|
|
671
748
|
: new PublicKey(metadataAddress),
|
|
672
|
-
|
|
749
|
+
mint: options.fromToken.mint,
|
|
673
750
|
ntt: nttPdas,
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
feeSource: getAssociatedTokenAddressSync(options.feeConfig.mint, options.walletPublicKey),
|
|
751
|
+
source: getAssociatedTokenAddressSync(options.fromToken.mint, options.walletPublicKey),
|
|
752
|
+
sponsor: options.context.internalPayer,
|
|
677
753
|
})
|
|
678
754
|
.instruction(),
|
|
679
755
|
]);
|
|
@@ -681,10 +757,10 @@ export const bridgeOut = async (options) => {
|
|
|
681
757
|
ComputeBudgetProgram.setComputeUnitLimit({ units: BRIDGE_OUT_CUS }),
|
|
682
758
|
...instructions,
|
|
683
759
|
], options.walletPublicKey, {
|
|
684
|
-
variation: "Intent NTT Bridge",
|
|
685
|
-
paymasterDomain: SESSIONS_INTERNAL_PAYMASTER_DOMAIN,
|
|
686
|
-
extraSigners: [outboxItem],
|
|
687
760
|
addressLookupTable: BRIDGING_ADDRESS_LOOKUP_TABLE[options.context.network]?.[options.fromToken.mint.toBase58()],
|
|
761
|
+
extraSigners: [outboxItem],
|
|
762
|
+
paymasterDomain: SESSIONS_INTERNAL_PAYMASTER_DOMAIN,
|
|
763
|
+
variation: "Intent NTT Bridge",
|
|
688
764
|
});
|
|
689
765
|
};
|
|
690
766
|
const getDestinationAtaExists = async (context, token, wallet) => {
|
|
@@ -726,16 +802,18 @@ const getNttPdas = async (options, wh, program, outboxItemPublicKey, quotePayeeA
|
|
|
726
802
|
nttTokenAuthority: pdas.tokenAuthority(),
|
|
727
803
|
payeeNttWithExecutor: quotePayeeAddress,
|
|
728
804
|
transceiver: registeredTransceiverPda,
|
|
729
|
-
wormholeProgram: coreBridgeContract,
|
|
730
805
|
wormholeBridge: wormholePdas.wormholeBridge,
|
|
731
806
|
wormholeFeeCollector: wormholePdas.wormholeFeeCollector,
|
|
732
807
|
wormholeMessage: transceiverPdas.wormholeMessageAccount(outboxItemPublicKey),
|
|
808
|
+
wormholeProgram: coreBridgeContract,
|
|
733
809
|
wormholeSequence: wormholePdas.wormholeSequence,
|
|
734
810
|
};
|
|
735
811
|
};
|
|
736
812
|
const buildBridgeOutIntent = async (program, options, decimals, symbol, feeToken, feeAmount) => {
|
|
737
813
|
const nonce = await getNonce(program, options.walletPublicKey, NonceType.Bridge);
|
|
738
|
-
return buildIntentInstruction(options, BRIDGE_OUT_MESSAGE_HEADER,
|
|
814
|
+
return buildIntentInstruction(options, BRIDGE_OUT_MESSAGE_HEADER,
|
|
815
|
+
// biome-ignore assist/source/useSortedKeys: The sort order is important here
|
|
816
|
+
{
|
|
739
817
|
version: `${CURRENT_BRIDGE_OUT_MAJOR}.${CURRENT_BRIDGE_OUT_MINOR}`,
|
|
740
818
|
from_chain_id: options.context.chainId,
|
|
741
819
|
to_chain_id: "solana",
|
|
@@ -813,9 +891,9 @@ const buildWormholeTransfer = async (options, connection) => {
|
|
|
813
891
|
});
|
|
814
892
|
const route = new Route(wh);
|
|
815
893
|
const transferRequest = await routes.RouteTransferRequest.create(wh, {
|
|
894
|
+
destination: Wormhole.tokenId(options.toToken.chain, options.toToken.mint.toBase58()),
|
|
816
895
|
recipient: Wormhole.chainAddress(options.toToken.chain, options.walletPublicKey.toBase58()),
|
|
817
896
|
source: Wormhole.tokenId(options.fromToken.chain, options.fromToken.mint.toBase58()),
|
|
818
|
-
destination: Wormhole.tokenId(options.toToken.chain, options.toToken.mint.toBase58()),
|
|
819
897
|
});
|
|
820
898
|
const validated = await route.validate(transferRequest, {
|
|
821
899
|
amount: amountToString(options.amount, decimals),
|
|
@@ -823,11 +901,11 @@ const buildWormholeTransfer = async (options, connection) => {
|
|
|
823
901
|
});
|
|
824
902
|
if (validated.valid) {
|
|
825
903
|
return {
|
|
826
|
-
|
|
904
|
+
decimals,
|
|
827
905
|
route,
|
|
828
|
-
transferRequest,
|
|
829
906
|
transferParams: validated.params,
|
|
830
|
-
|
|
907
|
+
transferRequest,
|
|
908
|
+
wh,
|
|
831
909
|
};
|
|
832
910
|
}
|
|
833
911
|
else {
|
package/esm/instructions.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AnchorProvider } from "@coral-xyz/anchor";
|
|
2
2
|
import { TollboothIdl, TollboothProgram } from "@fogo/sessions-idls";
|
|
3
|
-
import { sha256 } from "@noble/hashes/sha2";
|
|
3
|
+
import { sha256 } from "@noble/hashes/sha2.js";
|
|
4
4
|
import { createAssociatedTokenAccountIdempotentInstruction, createCloseAccountInstruction, createSyncNativeInstruction, getAssociatedTokenAddressSync, NATIVE_MINT, } from "@solana/spl-token";
|
|
5
5
|
import { PublicKey, SystemProgram, TransactionInstruction, } from "@solana/web3.js";
|
|
6
6
|
const SESSION_WRAP_DISCRIMINATOR = 4_000_000;
|
|
@@ -17,17 +17,17 @@ export function createSystemProgramSessionWrapInstruction(sessionKey, walletPubl
|
|
|
17
17
|
view.setUint32(0, SESSION_WRAP_DISCRIMINATOR, true);
|
|
18
18
|
view.setBigUint64(4, amount, true);
|
|
19
19
|
return new TransactionInstruction({
|
|
20
|
-
|
|
20
|
+
data: Buffer.from(data),
|
|
21
21
|
keys: [
|
|
22
|
-
{
|
|
22
|
+
{ isSigner: false, isWritable: true, pubkey: walletPublicKey },
|
|
23
23
|
{
|
|
24
|
-
pubkey: getNativeMintAssociatedTokenAddressSync(walletPublicKey),
|
|
25
24
|
isSigner: false,
|
|
26
25
|
isWritable: true,
|
|
26
|
+
pubkey: getNativeMintAssociatedTokenAddressSync(walletPublicKey),
|
|
27
27
|
},
|
|
28
|
-
{
|
|
28
|
+
{ isSigner: true, isWritable: false, pubkey: sessionKey },
|
|
29
29
|
],
|
|
30
|
-
|
|
30
|
+
programId: SystemProgram.programId,
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
@@ -53,7 +53,7 @@ export function createSessionUnwrapInstruction(sessionKey, walletPublicKey) {
|
|
|
53
53
|
return createCloseAccountInstruction(getNativeMintAssociatedTokenAddressSync(walletPublicKey), walletPublicKey, sessionKey);
|
|
54
54
|
}
|
|
55
55
|
const getDomainTollRecipientAddress = (domain) => {
|
|
56
|
-
const hash = sha256(domain);
|
|
56
|
+
const hash = sha256(new TextEncoder().encode(domain));
|
|
57
57
|
return PublicKey.findProgramAddressSync([Buffer.from("toll_recipient"), Buffer.from([0]), hash], new PublicKey(TollboothIdl.address))[0];
|
|
58
58
|
};
|
|
59
59
|
/**
|
|
@@ -66,10 +66,10 @@ export const createPaymasterFeeInstruction = ({ sessionKey, walletPublicKey, dom
|
|
|
66
66
|
return new TollboothProgram(new AnchorProvider({}, {})).methods
|
|
67
67
|
.payToll(feeAmount, 0)
|
|
68
68
|
.accounts({
|
|
69
|
-
session: sessionKey,
|
|
70
|
-
source: getAssociatedTokenAddressSync(feeMint, walletPublicKey),
|
|
71
69
|
destination: getAssociatedTokenAddressSync(feeMint, recipient, true),
|
|
72
70
|
mint: feeMint,
|
|
71
|
+
session: sessionKey,
|
|
72
|
+
source: getAssociatedTokenAddressSync(feeMint, walletPublicKey),
|
|
73
73
|
})
|
|
74
74
|
.instruction();
|
|
75
75
|
};
|
package/package.json
CHANGED
|
@@ -1,54 +1,55 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"@coral-xyz/anchor": "^0.32.1",
|
|
4
|
+
"@metaplex-foundation/mpl-token-metadata": "^3.4.0",
|
|
5
|
+
"@metaplex-foundation/umi": "^1.5.1",
|
|
6
|
+
"@metaplex-foundation/umi-bundle-defaults": "^1.5.1",
|
|
7
|
+
"@noble/hashes": "^2.2.0",
|
|
8
|
+
"@solana/compat": "^6.8.0",
|
|
9
|
+
"@solana/kit": "^6.8.0",
|
|
10
|
+
"@solana/spl-token": "^0.4.14",
|
|
11
|
+
"@solana/web3.js": "^1.98.4",
|
|
12
|
+
"@wormhole-foundation/sdk": "^4.17.0",
|
|
13
|
+
"@wormhole-foundation/sdk-base": "^4.17.0",
|
|
14
|
+
"@wormhole-foundation/sdk-connect": "^4.17.0",
|
|
15
|
+
"@wormhole-foundation/sdk-route-ntt": "^4.0.17",
|
|
16
|
+
"@wormhole-foundation/sdk-solana-core": "^4.17.0",
|
|
17
|
+
"@wormhole-foundation/sdk-solana-ntt": "^4.0.17",
|
|
18
|
+
"bn.js": "^5.2.3",
|
|
19
|
+
"bs58": "^6.0.0",
|
|
20
|
+
"zod": "4.3.6",
|
|
21
|
+
"@fogo/sessions-idls": "^0.1.4"
|
|
9
22
|
},
|
|
10
|
-
"
|
|
11
|
-
"fogo",
|
|
12
|
-
"sessions",
|
|
13
|
-
"crypto",
|
|
14
|
-
"wallet"
|
|
15
|
-
],
|
|
16
|
-
"type": "module",
|
|
17
|
-
"main": "./cjs/index.js",
|
|
18
|
-
"types": "./cjs/index.d.ts",
|
|
23
|
+
"description": "A set of utilities for integrating with Fogo sessions",
|
|
19
24
|
"engines": {
|
|
20
25
|
"node": ">=22"
|
|
21
26
|
},
|
|
22
27
|
"exports": {
|
|
23
28
|
".": {
|
|
24
29
|
"import": {
|
|
25
|
-
"
|
|
26
|
-
"
|
|
30
|
+
"default": "./esm/index.js",
|
|
31
|
+
"types": "./esm/index.d.ts"
|
|
27
32
|
},
|
|
28
33
|
"require": {
|
|
29
|
-
"
|
|
30
|
-
"
|
|
34
|
+
"default": "./cjs/index.js",
|
|
35
|
+
"types": "./cjs/index.d.ts"
|
|
31
36
|
}
|
|
32
37
|
}
|
|
33
38
|
},
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"bs58": "^6.0.0",
|
|
51
|
-
"zod": "3.25.67",
|
|
52
|
-
"@fogo/sessions-idls": "^0.1.2"
|
|
53
|
-
}
|
|
39
|
+
"keywords": [
|
|
40
|
+
"fogo",
|
|
41
|
+
"sessions",
|
|
42
|
+
"crypto",
|
|
43
|
+
"wallet"
|
|
44
|
+
],
|
|
45
|
+
"main": "./cjs/index.js",
|
|
46
|
+
"name": "@fogo/sessions-sdk",
|
|
47
|
+
"repository": {
|
|
48
|
+
"directory": "packages/sessions-sdk-ts",
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "https://github.com/fogo-foundation/fogo-sessions"
|
|
51
|
+
},
|
|
52
|
+
"type": "module",
|
|
53
|
+
"types": "./cjs/index.d.ts",
|
|
54
|
+
"version": "0.1.10"
|
|
54
55
|
}
|