@fogo/sessions-sdk 0.0.20 → 0.0.21
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/index.d.ts +16 -0
- package/cjs/index.js +80 -17
- package/esm/index.d.ts +16 -0
- package/esm/index.js +78 -17
- package/package.json +2 -2
package/cjs/index.d.ts
CHANGED
|
@@ -1310,6 +1310,20 @@ export type Session = {
|
|
|
1310
1310
|
sendTransaction: (instructions: Parameters<SessionContext["sendTransaction"]>[1]) => Promise<TransactionResult>;
|
|
1311
1311
|
sessionInfo: NonNullable<z.infer<typeof sessionInfoSchema>>;
|
|
1312
1312
|
};
|
|
1313
|
+
export declare const getTransferFee: (context: SessionContext) => Promise<{
|
|
1314
|
+
fee: bigint;
|
|
1315
|
+
metadata: import("@metaplex-foundation/umi").PublicKey<string>;
|
|
1316
|
+
mint: PublicKey;
|
|
1317
|
+
symbolOrMint: string;
|
|
1318
|
+
decimals: number;
|
|
1319
|
+
}>;
|
|
1320
|
+
export declare const getBridgeOutFee: (context: SessionContext) => Promise<{
|
|
1321
|
+
fee: bigint;
|
|
1322
|
+
metadata: import("@metaplex-foundation/umi").PublicKey<string>;
|
|
1323
|
+
mint: PublicKey;
|
|
1324
|
+
symbolOrMint: string;
|
|
1325
|
+
decimals: number;
|
|
1326
|
+
}>;
|
|
1313
1327
|
type SendTransferOptions = {
|
|
1314
1328
|
context: SessionContext;
|
|
1315
1329
|
walletPublicKey: PublicKey;
|
|
@@ -1317,6 +1331,7 @@ type SendTransferOptions = {
|
|
|
1317
1331
|
mint: PublicKey;
|
|
1318
1332
|
amount: bigint;
|
|
1319
1333
|
recipient: PublicKey;
|
|
1334
|
+
feeConfig: Awaited<ReturnType<typeof getTransferFee>>;
|
|
1320
1335
|
};
|
|
1321
1336
|
export declare const sendTransfer: (options: SendTransferOptions) => Promise<TransactionResult>;
|
|
1322
1337
|
type SendBridgeOutOptions = {
|
|
@@ -1332,6 +1347,7 @@ type SendBridgeOutOptions = {
|
|
|
1332
1347
|
toToken: WormholeToken & {
|
|
1333
1348
|
chain: "Solana";
|
|
1334
1349
|
};
|
|
1350
|
+
feeConfig: Awaited<ReturnType<typeof getBridgeOutFee>>;
|
|
1335
1351
|
};
|
|
1336
1352
|
type WormholeToken = {
|
|
1337
1353
|
chain: Chain;
|
package/cjs/index.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.verifyLogInToken = exports.createLogInToken = exports.bridgeIn = exports.bridgeOut = exports.sendTransfer = exports.SessionResultType = exports.getDomainRecordAddress = exports.AuthorizedTokens = exports.AuthorizedProgramsType = exports.getSessionAccount = exports.reestablishSession = exports.revokeSession = exports.replaceSession = exports.establishSession = exports.createSessionConnection = exports.TransactionResultType = exports.Network = exports.createSessionContext = void 0;
|
|
6
|
+
exports.verifyLogInToken = exports.createLogInToken = exports.bridgeIn = exports.bridgeOut = exports.sendTransfer = exports.getBridgeOutFee = exports.getTransferFee = exports.SessionResultType = exports.getDomainRecordAddress = exports.AuthorizedTokens = exports.AuthorizedProgramsType = exports.getSessionAccount = exports.reestablishSession = exports.revokeSession = exports.replaceSession = exports.establishSession = exports.createSessionConnection = exports.TransactionResultType = exports.Network = exports.createSessionContext = void 0;
|
|
7
7
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
8
8
|
const sessions_idls_1 = require("@fogo/sessions-idls");
|
|
9
9
|
const mpl_token_metadata_1 = require("@metaplex-foundation/mpl-token-metadata");
|
|
@@ -39,9 +39,9 @@ const TOKENLESS_PERMISSIONS_VALUE = "this app may not spend any tokens";
|
|
|
39
39
|
const CURRENT_MAJOR = "0";
|
|
40
40
|
const CURRENT_MINOR = "3";
|
|
41
41
|
const CURRENT_INTENT_TRANSFER_MAJOR = "0";
|
|
42
|
-
const CURRENT_INTENT_TRANSFER_MINOR = "
|
|
42
|
+
const CURRENT_INTENT_TRANSFER_MINOR = "2";
|
|
43
43
|
const CURRENT_BRIDGE_OUT_MAJOR = "0";
|
|
44
|
-
const CURRENT_BRIDGE_OUT_MINOR = "
|
|
44
|
+
const CURRENT_BRIDGE_OUT_MINOR = "2";
|
|
45
45
|
const SESSION_ESTABLISHMENT_LOOKUP_TABLE_ADDRESS = {
|
|
46
46
|
[connection_js_1.Network.Testnet]: "B8cUjJMqaWWTNNSTXBmeptjWswwCH1gTSCRYv4nu7kJW",
|
|
47
47
|
[connection_js_1.Network.Mainnet]: undefined,
|
|
@@ -448,7 +448,7 @@ const BRIDGING_ADDRESS_LOOKUP_TABLE = {
|
|
|
448
448
|
},
|
|
449
449
|
[connection_js_1.Network.Mainnet]: {
|
|
450
450
|
// USDC
|
|
451
|
-
|
|
451
|
+
uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG: "84k3mfNjmyinpZwyev7F15ChEW3Kqa3NoUkCJXXs4qkw",
|
|
452
452
|
},
|
|
453
453
|
};
|
|
454
454
|
const buildStartSessionInstruction = async (options, sessionKey, tokens) => {
|
|
@@ -502,12 +502,52 @@ const EstablishSessionResult = {
|
|
|
502
502
|
error,
|
|
503
503
|
}),
|
|
504
504
|
};
|
|
505
|
+
const USDC_MINT = {
|
|
506
|
+
[connection_js_1.Network.Mainnet]: "uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG",
|
|
507
|
+
[connection_js_1.Network.Testnet]: "ELNbJ1RtERV2fjtuZjbTscDekWhVzkQ1LjmiPsxp5uND",
|
|
508
|
+
};
|
|
509
|
+
const USDC_DECIMALS = 6;
|
|
510
|
+
const getTransferFee = async (context) => {
|
|
511
|
+
const { fee, ...config } = await getFee(context);
|
|
512
|
+
return {
|
|
513
|
+
...config,
|
|
514
|
+
fee: fee.intrachainTransfer,
|
|
515
|
+
};
|
|
516
|
+
};
|
|
517
|
+
exports.getTransferFee = getTransferFee;
|
|
518
|
+
const getBridgeOutFee = async (context) => {
|
|
519
|
+
const { fee, ...config } = await getFee(context);
|
|
520
|
+
return {
|
|
521
|
+
...config,
|
|
522
|
+
fee: fee.bridgeTransfer,
|
|
523
|
+
};
|
|
524
|
+
};
|
|
525
|
+
exports.getBridgeOutFee = getBridgeOutFee;
|
|
526
|
+
const getFee = async (context) => {
|
|
527
|
+
const program = new sessions_idls_1.IntentTransferProgram(new anchor_1.AnchorProvider(context.connection, {}, {}));
|
|
528
|
+
const umi = (0, umi_bundle_defaults_1.createUmi)(context.connection.rpcEndpoint);
|
|
529
|
+
const usdcMintAddress = USDC_MINT[context.network];
|
|
530
|
+
const usdcMint = new web3_js_1.PublicKey(usdcMintAddress);
|
|
531
|
+
const [feeConfigPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fee_config"), usdcMint.toBytes()], program.programId);
|
|
532
|
+
const feeConfig = await program.account.feeConfig.fetch(feeConfigPda);
|
|
533
|
+
return {
|
|
534
|
+
metadata: (0, mpl_token_metadata_1.findMetadataPda)(umi, {
|
|
535
|
+
mint: (0, umi_1.publicKey)(usdcMintAddress),
|
|
536
|
+
})[0],
|
|
537
|
+
mint: usdcMint,
|
|
538
|
+
symbolOrMint: context.network === connection_js_1.Network.Mainnet ? "USDC.s" : "USDC",
|
|
539
|
+
decimals: USDC_DECIMALS,
|
|
540
|
+
fee: {
|
|
541
|
+
intrachainTransfer: BigInt(feeConfig.intrachainTransferFee.toString()),
|
|
542
|
+
bridgeTransfer: BigInt(feeConfig.bridgeTransferFee.toString()),
|
|
543
|
+
},
|
|
544
|
+
};
|
|
545
|
+
};
|
|
505
546
|
const TRANSFER_MESSAGE_HEADER = `Fogo Transfer:
|
|
506
547
|
Signing this intent will transfer the tokens as described below.
|
|
507
548
|
`;
|
|
508
549
|
const sendTransfer = async (options) => {
|
|
509
550
|
const sourceAta = (0, spl_token_1.getAssociatedTokenAddressSync)(options.mint, options.walletPublicKey);
|
|
510
|
-
const destinationAta = (0, spl_token_1.getAssociatedTokenAddressSync)(options.mint, options.recipient);
|
|
511
551
|
const program = new sessions_idls_1.IntentTransferProgram(new anchor_1.AnchorProvider(options.context.connection, {}, {}));
|
|
512
552
|
const umi = (0, umi_bundle_defaults_1.createUmi)(options.context.connection.rpcEndpoint);
|
|
513
553
|
const metaplexMint = (0, umi_1.publicKey)(options.mint.toBase58());
|
|
@@ -515,12 +555,14 @@ const sendTransfer = async (options) => {
|
|
|
515
555
|
const metadata = await (0, mpl_token_metadata_1.safeFetchMetadata)(umi, metadataAddress);
|
|
516
556
|
const symbol = metadata?.symbol ?? undefined;
|
|
517
557
|
return options.context.sendTransaction(undefined, [
|
|
518
|
-
(
|
|
519
|
-
await buildTransferIntentInstruction(program, options, symbol),
|
|
558
|
+
await buildTransferIntentInstruction(program, options, symbol, options.feeConfig.symbolOrMint, amountToString(options.feeConfig.fee, options.feeConfig.decimals)),
|
|
520
559
|
await program.methods
|
|
521
560
|
.sendTokens()
|
|
522
561
|
.accounts({
|
|
523
|
-
|
|
562
|
+
destinationOwner: options.recipient,
|
|
563
|
+
feeMetadata: options.feeConfig.metadata,
|
|
564
|
+
feeMint: options.feeConfig.mint,
|
|
565
|
+
feeSource: (0, spl_token_1.getAssociatedTokenAddressSync)(options.feeConfig.mint, options.walletPublicKey),
|
|
524
566
|
mint: options.mint,
|
|
525
567
|
source: sourceAta,
|
|
526
568
|
sponsor: options.context.payer,
|
|
@@ -531,7 +573,7 @@ const sendTransfer = async (options) => {
|
|
|
531
573
|
]);
|
|
532
574
|
};
|
|
533
575
|
exports.sendTransfer = sendTransfer;
|
|
534
|
-
const buildTransferIntentInstruction = async (program, options, symbol) => {
|
|
576
|
+
const buildTransferIntentInstruction = async (program, options, symbol, feeToken, feeAmount) => {
|
|
535
577
|
const [nonce, { decimals }] = await Promise.all([
|
|
536
578
|
getNonce(program, options.walletPublicKey, NonceType.Transfer),
|
|
537
579
|
(0, spl_token_1.getMint)(options.context.connection, options.mint),
|
|
@@ -544,6 +586,8 @@ const buildTransferIntentInstruction = async (program, options, symbol) => {
|
|
|
544
586
|
token: symbol ?? options.mint.toBase58(),
|
|
545
587
|
amount: amountToString(options.amount, decimals),
|
|
546
588
|
recipient: options.recipient.toBase58(),
|
|
589
|
+
fee_token: feeToken,
|
|
590
|
+
fee_amount: feeAmount,
|
|
547
591
|
nonce: nonce === null ? "1" : nonce.nonce.add(new bn_js_1.default(1)).toString(),
|
|
548
592
|
}),
|
|
549
593
|
].join("\n"));
|
|
@@ -557,6 +601,7 @@ const buildTransferIntentInstruction = async (program, options, symbol) => {
|
|
|
557
601
|
const BRIDGE_OUT_MESSAGE_HEADER = `Fogo Bridge Transfer:
|
|
558
602
|
Signing this intent will bridge out the tokens as described below.
|
|
559
603
|
`;
|
|
604
|
+
const BRIDGE_OUT_CUS = 220_000;
|
|
560
605
|
const bridgeOut = async (options) => {
|
|
561
606
|
const { wh, route, transferRequest, transferParams, decimals } = await buildWormholeTransfer(options, options.context.connection);
|
|
562
607
|
// @ts-expect-error the wormhole client types are incorrect and do not
|
|
@@ -567,16 +612,16 @@ const bridgeOut = async (options) => {
|
|
|
567
612
|
const metaplexMint = (0, umi_1.publicKey)(options.fromToken.mint.toBase58());
|
|
568
613
|
const metadataAddress = (0, mpl_token_metadata_1.findMetadataPda)(umi, { mint: metaplexMint })[0];
|
|
569
614
|
const outboxItem = web3_js_1.Keypair.generate();
|
|
570
|
-
const [metadata, nttPdas] = await Promise.all([
|
|
615
|
+
const [metadata, nttPdas, destinationAtaExists] = await Promise.all([
|
|
571
616
|
(0, mpl_token_metadata_1.safeFetchMetadata)(umi, metadataAddress),
|
|
572
617
|
getNttPdas(options, wh, program, outboxItem.publicKey, new web3_js_1.PublicKey(quote.payeeAddress)),
|
|
618
|
+
getDestinationAtaExists(options.context, options.toToken.mint, options.walletPublicKey),
|
|
573
619
|
]);
|
|
574
|
-
|
|
575
|
-
buildBridgeOutIntent(program, options, decimals, metadata?.symbol),
|
|
620
|
+
const instructions = await Promise.all([
|
|
621
|
+
buildBridgeOutIntent(program, options, decimals, metadata?.symbol, options.feeConfig.symbolOrMint, amountToString(options.feeConfig.fee, options.feeConfig.decimals)),
|
|
576
622
|
program.methods
|
|
577
623
|
.bridgeNttTokens({
|
|
578
|
-
|
|
579
|
-
relayInstructions: Buffer.from(quote.relayInstructions),
|
|
624
|
+
payDestinationAtaRent: !destinationAtaExists,
|
|
580
625
|
signedQuoteBytes: Buffer.from(quote.signedQuote),
|
|
581
626
|
})
|
|
582
627
|
.accounts({
|
|
@@ -588,14 +633,26 @@ const bridgeOut = async (options) => {
|
|
|
588
633
|
: new web3_js_1.PublicKey(metadataAddress),
|
|
589
634
|
source: (0, spl_token_1.getAssociatedTokenAddressSync)(options.fromToken.mint, options.walletPublicKey),
|
|
590
635
|
ntt: nttPdas,
|
|
636
|
+
feeMetadata: options.feeConfig.metadata,
|
|
637
|
+
feeMint: options.feeConfig.mint,
|
|
638
|
+
feeSource: (0, spl_token_1.getAssociatedTokenAddressSync)(options.feeConfig.mint, options.walletPublicKey),
|
|
591
639
|
})
|
|
592
640
|
.instruction(),
|
|
593
|
-
])
|
|
641
|
+
]);
|
|
642
|
+
return options.context.sendTransaction(options.sessionKey, [
|
|
643
|
+
web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: BRIDGE_OUT_CUS }),
|
|
644
|
+
...instructions,
|
|
645
|
+
], {
|
|
594
646
|
extraSigners: [outboxItem],
|
|
595
647
|
addressLookupTable: BRIDGING_ADDRESS_LOOKUP_TABLE[options.context.network]?.[options.fromToken.mint.toBase58()],
|
|
596
648
|
});
|
|
597
649
|
};
|
|
598
650
|
exports.bridgeOut = bridgeOut;
|
|
651
|
+
const getDestinationAtaExists = async (context, token, wallet) => {
|
|
652
|
+
const solanaConnection = await context.getSolanaConnection();
|
|
653
|
+
const ataAccount = await solanaConnection.getAccountInfo((0, spl_token_1.getAssociatedTokenAddressSync)(token, wallet));
|
|
654
|
+
return ataAccount !== null;
|
|
655
|
+
};
|
|
599
656
|
// Here we use the Wormhole SDKs to produce the wormhole pdas that are needed
|
|
600
657
|
// for the bridge out transaction. Currently this is using wormhole SDK apis
|
|
601
658
|
// that are _technically_ public but it seems likely these are not considered to
|
|
@@ -613,6 +670,10 @@ const getNttPdas = async (options, wh, program, outboxItemPublicKey, quotePayeeA
|
|
|
613
670
|
const transceiverPdas = sdk_solana_ntt_1.NTT.transceiverPdas(options.fromToken.manager);
|
|
614
671
|
const [intentTransferSetterPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("intent_transfer")], program.programId);
|
|
615
672
|
const wormholePdas = sdk_solana_core_1.utils.getWormholeDerivedAccounts(options.fromToken.manager, coreBridgeContract);
|
|
673
|
+
const [registeredTransceiverPda] = web3_js_1.PublicKey.findProgramAddressSync([
|
|
674
|
+
Buffer.from("registered_transceiver"),
|
|
675
|
+
options.fromToken.manager.toBytes(),
|
|
676
|
+
], options.fromToken.manager);
|
|
616
677
|
return {
|
|
617
678
|
emitter: transceiverPdas.emitterAccount(),
|
|
618
679
|
nttConfig: pdas.configAccount(),
|
|
@@ -625,7 +686,7 @@ const getNttPdas = async (options, wh, program, outboxItemPublicKey, quotePayeeA
|
|
|
625
686
|
nttSessionAuthority: pdas.sessionAuthority(intentTransferSetterPda, sdk_solana_ntt_1.NTT.transferArgs(options.amount, sdk_1.Wormhole.chainAddress("Solana", options.walletPublicKey.toBase58()), false)),
|
|
626
687
|
nttTokenAuthority: pdas.tokenAuthority(),
|
|
627
688
|
payeeNttWithExecutor: quotePayeeAddress,
|
|
628
|
-
transceiver:
|
|
689
|
+
transceiver: registeredTransceiverPda,
|
|
629
690
|
wormholeProgram: coreBridgeContract,
|
|
630
691
|
wormholeBridge: wormholePdas.wormholeBridge,
|
|
631
692
|
wormholeFeeCollector: wormholePdas.wormholeFeeCollector,
|
|
@@ -633,7 +694,7 @@ const getNttPdas = async (options, wh, program, outboxItemPublicKey, quotePayeeA
|
|
|
633
694
|
wormholeSequence: wormholePdas.wormholeSequence,
|
|
634
695
|
};
|
|
635
696
|
};
|
|
636
|
-
const buildBridgeOutIntent = async (program, options, decimals, symbol) => {
|
|
697
|
+
const buildBridgeOutIntent = async (program, options, decimals, symbol, feeToken, feeAmount) => {
|
|
637
698
|
const nonce = await getNonce(program, options.walletPublicKey, NonceType.Bridge);
|
|
638
699
|
const message = new TextEncoder().encode([
|
|
639
700
|
BRIDGE_OUT_MESSAGE_HEADER,
|
|
@@ -644,6 +705,8 @@ const buildBridgeOutIntent = async (program, options, decimals, symbol) => {
|
|
|
644
705
|
token: symbol ?? options.fromToken.mint.toBase58(),
|
|
645
706
|
amount: amountToString(options.amount, decimals),
|
|
646
707
|
recipient_address: options.walletPublicKey.toBase58(),
|
|
708
|
+
fee_token: feeToken,
|
|
709
|
+
fee_amount: feeAmount,
|
|
647
710
|
nonce: nonce === null ? "1" : nonce.nonce.add(new bn_js_1.default(1)).toString(),
|
|
648
711
|
}),
|
|
649
712
|
].join("\n"));
|
package/esm/index.d.ts
CHANGED
|
@@ -1310,6 +1310,20 @@ export type Session = {
|
|
|
1310
1310
|
sendTransaction: (instructions: Parameters<SessionContext["sendTransaction"]>[1]) => Promise<TransactionResult>;
|
|
1311
1311
|
sessionInfo: NonNullable<z.infer<typeof sessionInfoSchema>>;
|
|
1312
1312
|
};
|
|
1313
|
+
export declare const getTransferFee: (context: SessionContext) => Promise<{
|
|
1314
|
+
fee: bigint;
|
|
1315
|
+
metadata: import("@metaplex-foundation/umi").PublicKey<string>;
|
|
1316
|
+
mint: PublicKey;
|
|
1317
|
+
symbolOrMint: string;
|
|
1318
|
+
decimals: number;
|
|
1319
|
+
}>;
|
|
1320
|
+
export declare const getBridgeOutFee: (context: SessionContext) => Promise<{
|
|
1321
|
+
fee: bigint;
|
|
1322
|
+
metadata: import("@metaplex-foundation/umi").PublicKey<string>;
|
|
1323
|
+
mint: PublicKey;
|
|
1324
|
+
symbolOrMint: string;
|
|
1325
|
+
decimals: number;
|
|
1326
|
+
}>;
|
|
1313
1327
|
type SendTransferOptions = {
|
|
1314
1328
|
context: SessionContext;
|
|
1315
1329
|
walletPublicKey: PublicKey;
|
|
@@ -1317,6 +1331,7 @@ type SendTransferOptions = {
|
|
|
1317
1331
|
mint: PublicKey;
|
|
1318
1332
|
amount: bigint;
|
|
1319
1333
|
recipient: PublicKey;
|
|
1334
|
+
feeConfig: Awaited<ReturnType<typeof getTransferFee>>;
|
|
1320
1335
|
};
|
|
1321
1336
|
export declare const sendTransfer: (options: SendTransferOptions) => Promise<TransactionResult>;
|
|
1322
1337
|
type SendBridgeOutOptions = {
|
|
@@ -1332,6 +1347,7 @@ type SendBridgeOutOptions = {
|
|
|
1332
1347
|
toToken: WormholeToken & {
|
|
1333
1348
|
chain: "Solana";
|
|
1334
1349
|
};
|
|
1350
|
+
feeConfig: Awaited<ReturnType<typeof getBridgeOutFee>>;
|
|
1335
1351
|
};
|
|
1336
1352
|
type WormholeToken = {
|
|
1337
1353
|
chain: Chain;
|
package/esm/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { sha256 } from "@noble/hashes/sha2";
|
|
|
7
7
|
import { fromLegacyPublicKey } from "@solana/compat";
|
|
8
8
|
import { generateKeyPair, getAddressFromPublicKey, getProgramDerivedAddress, signatureBytes, verifySignature, } from "@solana/kit";
|
|
9
9
|
import { createAssociatedTokenAccountIdempotentInstruction, getAssociatedTokenAddressSync, getMint, } from "@solana/spl-token";
|
|
10
|
-
import { Connection, Ed25519Program, Keypair, PublicKey, } from "@solana/web3.js";
|
|
10
|
+
import { ComputeBudgetProgram, Connection, Ed25519Program, Keypair, PublicKey, } from "@solana/web3.js";
|
|
11
11
|
import { Wormhole, wormhole, routes } from "@wormhole-foundation/sdk";
|
|
12
12
|
import solanaSdk from "@wormhole-foundation/sdk/solana";
|
|
13
13
|
import { contracts } from "@wormhole-foundation/sdk-base";
|
|
@@ -29,9 +29,9 @@ const TOKENLESS_PERMISSIONS_VALUE = "this app may not spend any tokens";
|
|
|
29
29
|
const CURRENT_MAJOR = "0";
|
|
30
30
|
const CURRENT_MINOR = "3";
|
|
31
31
|
const CURRENT_INTENT_TRANSFER_MAJOR = "0";
|
|
32
|
-
const CURRENT_INTENT_TRANSFER_MINOR = "
|
|
32
|
+
const CURRENT_INTENT_TRANSFER_MINOR = "2";
|
|
33
33
|
const CURRENT_BRIDGE_OUT_MAJOR = "0";
|
|
34
|
-
const CURRENT_BRIDGE_OUT_MINOR = "
|
|
34
|
+
const CURRENT_BRIDGE_OUT_MINOR = "2";
|
|
35
35
|
const SESSION_ESTABLISHMENT_LOOKUP_TABLE_ADDRESS = {
|
|
36
36
|
[Network.Testnet]: "B8cUjJMqaWWTNNSTXBmeptjWswwCH1gTSCRYv4nu7kJW",
|
|
37
37
|
[Network.Mainnet]: undefined,
|
|
@@ -432,7 +432,7 @@ const BRIDGING_ADDRESS_LOOKUP_TABLE = {
|
|
|
432
432
|
},
|
|
433
433
|
[Network.Mainnet]: {
|
|
434
434
|
// USDC
|
|
435
|
-
|
|
435
|
+
uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG: "84k3mfNjmyinpZwyev7F15ChEW3Kqa3NoUkCJXXs4qkw",
|
|
436
436
|
},
|
|
437
437
|
};
|
|
438
438
|
const buildStartSessionInstruction = async (options, sessionKey, tokens) => {
|
|
@@ -486,12 +486,50 @@ const EstablishSessionResult = {
|
|
|
486
486
|
error,
|
|
487
487
|
}),
|
|
488
488
|
};
|
|
489
|
+
const USDC_MINT = {
|
|
490
|
+
[Network.Mainnet]: "uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG",
|
|
491
|
+
[Network.Testnet]: "ELNbJ1RtERV2fjtuZjbTscDekWhVzkQ1LjmiPsxp5uND",
|
|
492
|
+
};
|
|
493
|
+
const USDC_DECIMALS = 6;
|
|
494
|
+
export const getTransferFee = async (context) => {
|
|
495
|
+
const { fee, ...config } = await getFee(context);
|
|
496
|
+
return {
|
|
497
|
+
...config,
|
|
498
|
+
fee: fee.intrachainTransfer,
|
|
499
|
+
};
|
|
500
|
+
};
|
|
501
|
+
export const getBridgeOutFee = async (context) => {
|
|
502
|
+
const { fee, ...config } = await getFee(context);
|
|
503
|
+
return {
|
|
504
|
+
...config,
|
|
505
|
+
fee: fee.bridgeTransfer,
|
|
506
|
+
};
|
|
507
|
+
};
|
|
508
|
+
const getFee = async (context) => {
|
|
509
|
+
const program = new IntentTransferProgram(new AnchorProvider(context.connection, {}, {}));
|
|
510
|
+
const umi = createUmi(context.connection.rpcEndpoint);
|
|
511
|
+
const usdcMintAddress = USDC_MINT[context.network];
|
|
512
|
+
const usdcMint = new PublicKey(usdcMintAddress);
|
|
513
|
+
const [feeConfigPda] = PublicKey.findProgramAddressSync([Buffer.from("fee_config"), usdcMint.toBytes()], program.programId);
|
|
514
|
+
const feeConfig = await program.account.feeConfig.fetch(feeConfigPda);
|
|
515
|
+
return {
|
|
516
|
+
metadata: findMetadataPda(umi, {
|
|
517
|
+
mint: metaplexPublicKey(usdcMintAddress),
|
|
518
|
+
})[0],
|
|
519
|
+
mint: usdcMint,
|
|
520
|
+
symbolOrMint: context.network === Network.Mainnet ? "USDC.s" : "USDC",
|
|
521
|
+
decimals: USDC_DECIMALS,
|
|
522
|
+
fee: {
|
|
523
|
+
intrachainTransfer: BigInt(feeConfig.intrachainTransferFee.toString()),
|
|
524
|
+
bridgeTransfer: BigInt(feeConfig.bridgeTransferFee.toString()),
|
|
525
|
+
},
|
|
526
|
+
};
|
|
527
|
+
};
|
|
489
528
|
const TRANSFER_MESSAGE_HEADER = `Fogo Transfer:
|
|
490
529
|
Signing this intent will transfer the tokens as described below.
|
|
491
530
|
`;
|
|
492
531
|
export const sendTransfer = async (options) => {
|
|
493
532
|
const sourceAta = getAssociatedTokenAddressSync(options.mint, options.walletPublicKey);
|
|
494
|
-
const destinationAta = getAssociatedTokenAddressSync(options.mint, options.recipient);
|
|
495
533
|
const program = new IntentTransferProgram(new AnchorProvider(options.context.connection, {}, {}));
|
|
496
534
|
const umi = createUmi(options.context.connection.rpcEndpoint);
|
|
497
535
|
const metaplexMint = metaplexPublicKey(options.mint.toBase58());
|
|
@@ -499,12 +537,14 @@ export const sendTransfer = async (options) => {
|
|
|
499
537
|
const metadata = await safeFetchMetadata(umi, metadataAddress);
|
|
500
538
|
const symbol = metadata?.symbol ?? undefined;
|
|
501
539
|
return options.context.sendTransaction(undefined, [
|
|
502
|
-
|
|
503
|
-
await buildTransferIntentInstruction(program, options, symbol),
|
|
540
|
+
await buildTransferIntentInstruction(program, options, symbol, options.feeConfig.symbolOrMint, amountToString(options.feeConfig.fee, options.feeConfig.decimals)),
|
|
504
541
|
await program.methods
|
|
505
542
|
.sendTokens()
|
|
506
543
|
.accounts({
|
|
507
|
-
|
|
544
|
+
destinationOwner: options.recipient,
|
|
545
|
+
feeMetadata: options.feeConfig.metadata,
|
|
546
|
+
feeMint: options.feeConfig.mint,
|
|
547
|
+
feeSource: getAssociatedTokenAddressSync(options.feeConfig.mint, options.walletPublicKey),
|
|
508
548
|
mint: options.mint,
|
|
509
549
|
source: sourceAta,
|
|
510
550
|
sponsor: options.context.payer,
|
|
@@ -514,7 +554,7 @@ export const sendTransfer = async (options) => {
|
|
|
514
554
|
.instruction(),
|
|
515
555
|
]);
|
|
516
556
|
};
|
|
517
|
-
const buildTransferIntentInstruction = async (program, options, symbol) => {
|
|
557
|
+
const buildTransferIntentInstruction = async (program, options, symbol, feeToken, feeAmount) => {
|
|
518
558
|
const [nonce, { decimals }] = await Promise.all([
|
|
519
559
|
getNonce(program, options.walletPublicKey, NonceType.Transfer),
|
|
520
560
|
getMint(options.context.connection, options.mint),
|
|
@@ -527,6 +567,8 @@ const buildTransferIntentInstruction = async (program, options, symbol) => {
|
|
|
527
567
|
token: symbol ?? options.mint.toBase58(),
|
|
528
568
|
amount: amountToString(options.amount, decimals),
|
|
529
569
|
recipient: options.recipient.toBase58(),
|
|
570
|
+
fee_token: feeToken,
|
|
571
|
+
fee_amount: feeAmount,
|
|
530
572
|
nonce: nonce === null ? "1" : nonce.nonce.add(new BN(1)).toString(),
|
|
531
573
|
}),
|
|
532
574
|
].join("\n"));
|
|
@@ -540,6 +582,7 @@ const buildTransferIntentInstruction = async (program, options, symbol) => {
|
|
|
540
582
|
const BRIDGE_OUT_MESSAGE_HEADER = `Fogo Bridge Transfer:
|
|
541
583
|
Signing this intent will bridge out the tokens as described below.
|
|
542
584
|
`;
|
|
585
|
+
const BRIDGE_OUT_CUS = 220_000;
|
|
543
586
|
export const bridgeOut = async (options) => {
|
|
544
587
|
const { wh, route, transferRequest, transferParams, decimals } = await buildWormholeTransfer(options, options.context.connection);
|
|
545
588
|
// @ts-expect-error the wormhole client types are incorrect and do not
|
|
@@ -550,16 +593,16 @@ export const bridgeOut = async (options) => {
|
|
|
550
593
|
const metaplexMint = metaplexPublicKey(options.fromToken.mint.toBase58());
|
|
551
594
|
const metadataAddress = findMetadataPda(umi, { mint: metaplexMint })[0];
|
|
552
595
|
const outboxItem = Keypair.generate();
|
|
553
|
-
const [metadata, nttPdas] = await Promise.all([
|
|
596
|
+
const [metadata, nttPdas, destinationAtaExists] = await Promise.all([
|
|
554
597
|
safeFetchMetadata(umi, metadataAddress),
|
|
555
598
|
getNttPdas(options, wh, program, outboxItem.publicKey, new PublicKey(quote.payeeAddress)),
|
|
599
|
+
getDestinationAtaExists(options.context, options.toToken.mint, options.walletPublicKey),
|
|
556
600
|
]);
|
|
557
|
-
|
|
558
|
-
buildBridgeOutIntent(program, options, decimals, metadata?.symbol),
|
|
601
|
+
const instructions = await Promise.all([
|
|
602
|
+
buildBridgeOutIntent(program, options, decimals, metadata?.symbol, options.feeConfig.symbolOrMint, amountToString(options.feeConfig.fee, options.feeConfig.decimals)),
|
|
559
603
|
program.methods
|
|
560
604
|
.bridgeNttTokens({
|
|
561
|
-
|
|
562
|
-
relayInstructions: Buffer.from(quote.relayInstructions),
|
|
605
|
+
payDestinationAtaRent: !destinationAtaExists,
|
|
563
606
|
signedQuoteBytes: Buffer.from(quote.signedQuote),
|
|
564
607
|
})
|
|
565
608
|
.accounts({
|
|
@@ -571,13 +614,25 @@ export const bridgeOut = async (options) => {
|
|
|
571
614
|
: new PublicKey(metadataAddress),
|
|
572
615
|
source: getAssociatedTokenAddressSync(options.fromToken.mint, options.walletPublicKey),
|
|
573
616
|
ntt: nttPdas,
|
|
617
|
+
feeMetadata: options.feeConfig.metadata,
|
|
618
|
+
feeMint: options.feeConfig.mint,
|
|
619
|
+
feeSource: getAssociatedTokenAddressSync(options.feeConfig.mint, options.walletPublicKey),
|
|
574
620
|
})
|
|
575
621
|
.instruction(),
|
|
576
|
-
])
|
|
622
|
+
]);
|
|
623
|
+
return options.context.sendTransaction(options.sessionKey, [
|
|
624
|
+
ComputeBudgetProgram.setComputeUnitLimit({ units: BRIDGE_OUT_CUS }),
|
|
625
|
+
...instructions,
|
|
626
|
+
], {
|
|
577
627
|
extraSigners: [outboxItem],
|
|
578
628
|
addressLookupTable: BRIDGING_ADDRESS_LOOKUP_TABLE[options.context.network]?.[options.fromToken.mint.toBase58()],
|
|
579
629
|
});
|
|
580
630
|
};
|
|
631
|
+
const getDestinationAtaExists = async (context, token, wallet) => {
|
|
632
|
+
const solanaConnection = await context.getSolanaConnection();
|
|
633
|
+
const ataAccount = await solanaConnection.getAccountInfo(getAssociatedTokenAddressSync(token, wallet));
|
|
634
|
+
return ataAccount !== null;
|
|
635
|
+
};
|
|
581
636
|
// Here we use the Wormhole SDKs to produce the wormhole pdas that are needed
|
|
582
637
|
// for the bridge out transaction. Currently this is using wormhole SDK apis
|
|
583
638
|
// that are _technically_ public but it seems likely these are not considered to
|
|
@@ -595,6 +650,10 @@ const getNttPdas = async (options, wh, program, outboxItemPublicKey, quotePayeeA
|
|
|
595
650
|
const transceiverPdas = NTT.transceiverPdas(options.fromToken.manager);
|
|
596
651
|
const [intentTransferSetterPda] = PublicKey.findProgramAddressSync([Buffer.from("intent_transfer")], program.programId);
|
|
597
652
|
const wormholePdas = utils.getWormholeDerivedAccounts(options.fromToken.manager, coreBridgeContract);
|
|
653
|
+
const [registeredTransceiverPda] = PublicKey.findProgramAddressSync([
|
|
654
|
+
Buffer.from("registered_transceiver"),
|
|
655
|
+
options.fromToken.manager.toBytes(),
|
|
656
|
+
], options.fromToken.manager);
|
|
598
657
|
return {
|
|
599
658
|
emitter: transceiverPdas.emitterAccount(),
|
|
600
659
|
nttConfig: pdas.configAccount(),
|
|
@@ -607,7 +666,7 @@ const getNttPdas = async (options, wh, program, outboxItemPublicKey, quotePayeeA
|
|
|
607
666
|
nttSessionAuthority: pdas.sessionAuthority(intentTransferSetterPda, NTT.transferArgs(options.amount, Wormhole.chainAddress("Solana", options.walletPublicKey.toBase58()), false)),
|
|
608
667
|
nttTokenAuthority: pdas.tokenAuthority(),
|
|
609
668
|
payeeNttWithExecutor: quotePayeeAddress,
|
|
610
|
-
transceiver:
|
|
669
|
+
transceiver: registeredTransceiverPda,
|
|
611
670
|
wormholeProgram: coreBridgeContract,
|
|
612
671
|
wormholeBridge: wormholePdas.wormholeBridge,
|
|
613
672
|
wormholeFeeCollector: wormholePdas.wormholeFeeCollector,
|
|
@@ -615,7 +674,7 @@ const getNttPdas = async (options, wh, program, outboxItemPublicKey, quotePayeeA
|
|
|
615
674
|
wormholeSequence: wormholePdas.wormholeSequence,
|
|
616
675
|
};
|
|
617
676
|
};
|
|
618
|
-
const buildBridgeOutIntent = async (program, options, decimals, symbol) => {
|
|
677
|
+
const buildBridgeOutIntent = async (program, options, decimals, symbol, feeToken, feeAmount) => {
|
|
619
678
|
const nonce = await getNonce(program, options.walletPublicKey, NonceType.Bridge);
|
|
620
679
|
const message = new TextEncoder().encode([
|
|
621
680
|
BRIDGE_OUT_MESSAGE_HEADER,
|
|
@@ -626,6 +685,8 @@ const buildBridgeOutIntent = async (program, options, decimals, symbol) => {
|
|
|
626
685
|
token: symbol ?? options.fromToken.mint.toBase58(),
|
|
627
686
|
amount: amountToString(options.amount, decimals),
|
|
628
687
|
recipient_address: options.walletPublicKey.toBase58(),
|
|
688
|
+
fee_token: feeToken,
|
|
689
|
+
fee_amount: feeAmount,
|
|
629
690
|
nonce: nonce === null ? "1" : nonce.nonce.add(new BN(1)).toString(),
|
|
630
691
|
}),
|
|
631
692
|
].join("\n"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fogo/sessions-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"description": "A set of utilities for integrating with Fogo sessions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fogo",
|
|
@@ -44,6 +44,6 @@
|
|
|
44
44
|
"bn.js": "^5.1.2",
|
|
45
45
|
"bs58": "^6.0.0",
|
|
46
46
|
"zod": "^3.25.62",
|
|
47
|
-
"@fogo/sessions-idls": "^0.0.
|
|
47
|
+
"@fogo/sessions-idls": "^0.0.9"
|
|
48
48
|
}
|
|
49
49
|
}
|