@fogo/sessions-sdk 0.0.21 → 0.0.23

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.
@@ -1,4 +1,4 @@
1
- import type { Transaction, Instruction, TransactionWithLifetime } from "@solana/kit";
1
+ import type { Transaction, Instruction, TransactionWithLifetime, Rpc, GetLatestBlockhashApi } from "@solana/kit";
2
2
  import type { TransactionError } from "@solana/web3.js";
3
3
  import { Keypair, Connection as Web3Connection, TransactionInstruction, VersionedTransaction, PublicKey } from "@solana/web3.js";
4
4
  export declare enum Network {
@@ -33,15 +33,18 @@ export declare const createSessionConnection: (options: {
33
33
  sendToPaymaster: (transaction: Transaction) => Promise<TransactionResult>;
34
34
  sponsor: PublicKey;
35
35
  })) => {
36
- rpc: import("@solana/kit").Rpc<import("@solana/kit").RequestAirdropApi & import("@solana/kit").GetAccountInfoApi & import("@solana/kit").GetBalanceApi & import("@solana/kit").GetBlockApi & import("@solana/kit").GetBlockCommitmentApi & import("@solana/kit").GetBlockHeightApi & import("@solana/kit").GetBlockProductionApi & import("@solana/kit").GetBlocksApi & import("@solana/kit").GetBlocksWithLimitApi & import("@solana/kit").GetBlockTimeApi & import("@solana/kit").GetClusterNodesApi & import("@solana/kit").GetEpochInfoApi & import("@solana/kit").GetEpochScheduleApi & import("@solana/kit").GetFeeForMessageApi & import("@solana/kit").GetFirstAvailableBlockApi & import("@solana/kit").GetGenesisHashApi & import("@solana/kit").GetHealthApi & import("@solana/kit").GetHighestSnapshotSlotApi & import("@solana/kit").GetIdentityApi & import("@solana/kit").GetInflationGovernorApi & import("@solana/kit").GetInflationRateApi & import("@solana/kit").GetInflationRewardApi & import("@solana/kit").GetLargestAccountsApi & import("@solana/kit").GetLatestBlockhashApi & import("@solana/kit").GetLeaderScheduleApi & import("@solana/kit").GetMaxRetransmitSlotApi & import("@solana/kit").GetMaxShredInsertSlotApi & import("@solana/kit").GetMinimumBalanceForRentExemptionApi & import("@solana/kit").GetMultipleAccountsApi & import("@solana/kit").GetProgramAccountsApi & import("@solana/kit").GetRecentPerformanceSamplesApi & import("@solana/kit").GetRecentPrioritizationFeesApi & import("@solana/kit").GetSignaturesForAddressApi & import("@solana/kit").GetSignatureStatusesApi & import("@solana/kit").GetSlotApi & import("@solana/kit").GetSlotLeaderApi & import("@solana/kit").GetSlotLeadersApi & import("@solana/kit").GetStakeMinimumDelegationApi & import("@solana/kit").GetSupplyApi & import("@solana/kit").GetTokenAccountBalanceApi & import("@solana/kit").GetTokenAccountsByDelegateApi & import("@solana/kit").GetTokenAccountsByOwnerApi & import("@solana/kit").GetTokenLargestAccountsApi & import("@solana/kit").GetTokenSupplyApi & import("@solana/kit").GetTransactionApi & import("@solana/kit").GetTransactionCountApi & import("@solana/kit").GetVersionApi & import("@solana/kit").GetVoteAccountsApi & import("@solana/kit").IsBlockhashValidApi & import("@solana/kit").MinimumLedgerSlotApi & import("@solana/kit").SendTransactionApi & import("@solana/kit").SimulateTransactionApi>;
36
+ rpc: Rpc<import("@solana/kit").RequestAirdropApi & import("@solana/kit").GetAccountInfoApi & import("@solana/kit").GetBalanceApi & import("@solana/kit").GetBlockApi & import("@solana/kit").GetBlockCommitmentApi & import("@solana/kit").GetBlockHeightApi & import("@solana/kit").GetBlockProductionApi & import("@solana/kit").GetBlocksApi & import("@solana/kit").GetBlocksWithLimitApi & import("@solana/kit").GetBlockTimeApi & import("@solana/kit").GetClusterNodesApi & import("@solana/kit").GetEpochInfoApi & import("@solana/kit").GetEpochScheduleApi & import("@solana/kit").GetFeeForMessageApi & import("@solana/kit").GetFirstAvailableBlockApi & import("@solana/kit").GetGenesisHashApi & import("@solana/kit").GetHealthApi & import("@solana/kit").GetHighestSnapshotSlotApi & import("@solana/kit").GetIdentityApi & import("@solana/kit").GetInflationGovernorApi & import("@solana/kit").GetInflationRateApi & import("@solana/kit").GetInflationRewardApi & import("@solana/kit").GetLargestAccountsApi & GetLatestBlockhashApi & import("@solana/kit").GetLeaderScheduleApi & import("@solana/kit").GetMaxRetransmitSlotApi & import("@solana/kit").GetMaxShredInsertSlotApi & import("@solana/kit").GetMinimumBalanceForRentExemptionApi & import("@solana/kit").GetMultipleAccountsApi & import("@solana/kit").GetProgramAccountsApi & import("@solana/kit").GetRecentPerformanceSamplesApi & import("@solana/kit").GetRecentPrioritizationFeesApi & import("@solana/kit").GetSignaturesForAddressApi & import("@solana/kit").GetSignatureStatusesApi & import("@solana/kit").GetSlotApi & import("@solana/kit").GetSlotLeaderApi & import("@solana/kit").GetSlotLeadersApi & import("@solana/kit").GetStakeMinimumDelegationApi & import("@solana/kit").GetSupplyApi & import("@solana/kit").GetTokenAccountBalanceApi & import("@solana/kit").GetTokenAccountsByDelegateApi & import("@solana/kit").GetTokenAccountsByOwnerApi & import("@solana/kit").GetTokenLargestAccountsApi & import("@solana/kit").GetTokenSupplyApi & import("@solana/kit").GetTransactionApi & import("@solana/kit").GetTransactionCountApi & import("@solana/kit").GetVersionApi & import("@solana/kit").GetVoteAccountsApi & import("@solana/kit").IsBlockhashValidApi & import("@solana/kit").MinimumLedgerSlotApi & import("@solana/kit").SendTransactionApi & import("@solana/kit").SimulateTransactionApi>;
37
37
  connection: Web3Connection;
38
38
  network: Network;
39
39
  getSolanaConnection: () => Promise<Web3Connection>;
40
- sendToPaymaster: (domain: string, sponsor: PublicKey, sessionKey: CryptoKeyPair | undefined, instructions: (TransactionInstruction | Instruction)[] | VersionedTransaction | (Transaction & TransactionWithLifetime), extraConfig?: {
41
- addressLookupTable?: string | undefined;
42
- extraSigners?: (CryptoKeyPair | Keypair)[] | undefined;
43
- }) => Promise<TransactionResult>;
40
+ sendToPaymaster: (domain: string, sessionKey: CryptoKeyPair | undefined, instructions: TransactionOrInstructions, extraConfig?: SendTransactionOptions) => Promise<TransactionResult>;
44
41
  getSponsor: (domain: string) => Promise<PublicKey>;
45
42
  };
43
+ export type TransactionOrInstructions = (TransactionInstruction | Instruction)[] | VersionedTransaction | (Transaction & TransactionWithLifetime);
44
+ export type SendTransactionOptions = {
45
+ variation?: string | undefined;
46
+ addressLookupTable?: string | undefined;
47
+ extraSigners?: (CryptoKeyPair | Keypair)[] | undefined;
48
+ };
46
49
  export type Connection = ReturnType<typeof createSessionConnection>;
47
50
  export {};
package/cjs/connection.js CHANGED
@@ -39,17 +39,14 @@ const createSessionConnection = (options) => {
39
39
  const rpc = (0, kit_1.createSolanaRpc)(rpcUrl);
40
40
  const connection = new web3_js_1.Connection(rpcUrl, "confirmed");
41
41
  const addressLookupTableCache = new Map();
42
+ const sponsorCache = new Map();
42
43
  return {
43
44
  rpc,
44
45
  connection,
45
46
  network: options.network,
46
47
  getSolanaConnection: createSolanaConnectionGetter(options.network),
47
- sendToPaymaster: async (domain, sponsor, sessionKey, instructions, extraConfig) => {
48
- const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
49
- const transaction = await buildTransaction(connection, latestBlockhash, sessionKey, sponsor, instructions, addressLookupTableCache, extraConfig);
50
- return sendToPaymaster(options, domain, transaction);
51
- },
52
- getSponsor: (domain) => getSponsor(options, domain),
48
+ sendToPaymaster: async (domain, sessionKey, instructions, extraConfig) => sendToPaymaster({ ...options, rpc, connection, addressLookupTableCache, sponsorCache }, domain, sessionKey, instructions, extraConfig),
49
+ getSponsor: (domain) => getSponsor(options, sponsorCache, domain),
53
50
  };
54
51
  };
55
52
  exports.createSessionConnection = createSessionConnection;
@@ -75,10 +72,17 @@ const NETWORK_TO_QUERY_PARAM = {
75
72
  [Network.Mainnet]: "mainnet",
76
73
  [Network.Testnet]: "testnet",
77
74
  };
78
- const sendToPaymaster = async (options, domain, transaction) => {
79
- if (options.sendToPaymaster === undefined) {
80
- const url = new URL("/api/sponsor_and_send", options.paymaster ?? DEFAULT_PAYMASTER[options.network]);
75
+ const sendToPaymaster = async (connection, domain, sessionKey, instructions, extraConfig) => {
76
+ const signerKeys = await getSignerKeys(sessionKey, extraConfig?.extraSigners);
77
+ const transaction = Array.isArray(instructions)
78
+ ? await buildTransaction(connection, domain, signerKeys, instructions, extraConfig)
79
+ : await addSignaturesToExistingTransaction(instructions, signerKeys);
80
+ if (connection.sendToPaymaster === undefined) {
81
+ const url = new URL("/api/sponsor_and_send", connection.paymaster ?? DEFAULT_PAYMASTER[connection.network]);
81
82
  url.searchParams.set("domain", domain);
83
+ if (extraConfig?.variation !== undefined) {
84
+ url.searchParams.set("variation", extraConfig.variation);
85
+ }
82
86
  const response = await fetch(url, {
83
87
  method: "POST",
84
88
  headers: {
@@ -96,33 +100,31 @@ const sendToPaymaster = async (options, domain, transaction) => {
96
100
  }
97
101
  }
98
102
  else {
99
- return options.sendToPaymaster(transaction);
103
+ return connection.sendToPaymaster(transaction);
100
104
  }
101
105
  };
102
- const buildTransaction = async (connection, latestBlockhash, sessionKey, sponsor, instructions, addressLookupTableCache, extraConfig) => {
103
- const [signerKeys, addressLookupTable] = await Promise.all([
104
- getSignerKeys(sessionKey, extraConfig?.extraSigners),
106
+ const buildTransaction = async (connection, domain, signerKeys, instructions, extraConfig) => {
107
+ const [{ value: latestBlockhash }, sponsor, addressLookupTable, signers] = await Promise.all([
108
+ connection.rpc.getLatestBlockhash().send(),
109
+ connection.sponsor === undefined
110
+ ? getSponsor(connection, connection.sponsorCache, domain)
111
+ : Promise.resolve(connection.sponsor),
105
112
  extraConfig?.addressLookupTable === undefined
106
113
  ? Promise.resolve(undefined)
107
- : getAddressLookupTable(connection, addressLookupTableCache, extraConfig.addressLookupTable),
114
+ : getAddressLookupTable(connection.connection, connection.addressLookupTableCache, extraConfig.addressLookupTable),
115
+ Promise.all(signerKeys.map((signer) => (0, kit_1.createSignerFromKeyPair)(signer))),
108
116
  ]);
109
- if (Array.isArray(instructions)) {
110
- const signers = await Promise.all(signerKeys.map((signer) => (0, kit_1.createSignerFromKeyPair)(signer)));
111
- return (0, kit_1.partiallySignTransactionMessageWithSigners)((0, kit_1.pipe)((0, kit_1.createTransactionMessage)({ version: 0 }), (tx) => (0, kit_1.setTransactionMessageFeePayer)((0, compat_1.fromLegacyPublicKey)(sponsor), tx), (tx) => (0, kit_1.setTransactionMessageLifetimeUsingBlockhash)(latestBlockhash, tx), (tx) => (0, kit_1.appendTransactionMessageInstructions)(instructions.map((instruction) => instruction instanceof web3_js_1.TransactionInstruction
112
- ? (0, compat_1.fromLegacyTransactionInstruction)(instruction)
113
- : instruction), tx), (tx) => addressLookupTable === undefined
114
- ? tx
115
- : (0, kit_1.compressTransactionMessageUsingAddressLookupTables)(tx, {
116
- [(0, compat_1.fromLegacyPublicKey)(addressLookupTable.key)]: addressLookupTable.state.addresses.map((address) => (0, compat_1.fromLegacyPublicKey)(address)),
117
- }), (tx) => (0, kit_1.addSignersToTransactionMessage)(signers, tx)));
118
- }
119
- else {
120
- const tx = instructions instanceof web3_js_1.VersionedTransaction
121
- ? (0, compat_1.fromVersionedTransaction)(instructions) // VersionedTransaction has a lifetime so it's fine to cast it so we can call partiallySignTransaction
122
- : instructions;
123
- return (0, kit_1.partiallySignTransaction)(signerKeys, tx);
124
- }
117
+ return (0, kit_1.partiallySignTransactionMessageWithSigners)((0, kit_1.pipe)((0, kit_1.createTransactionMessage)({ version: 0 }), (tx) => (0, kit_1.setTransactionMessageFeePayer)((0, compat_1.fromLegacyPublicKey)(sponsor), tx), (tx) => (0, kit_1.setTransactionMessageLifetimeUsingBlockhash)(latestBlockhash, tx), (tx) => (0, kit_1.appendTransactionMessageInstructions)(instructions.map((instruction) => instruction instanceof web3_js_1.TransactionInstruction
118
+ ? (0, compat_1.fromLegacyTransactionInstruction)(instruction)
119
+ : instruction), tx), (tx) => addressLookupTable === undefined
120
+ ? tx
121
+ : (0, kit_1.compressTransactionMessageUsingAddressLookupTables)(tx, {
122
+ [(0, compat_1.fromLegacyPublicKey)(addressLookupTable.key)]: addressLookupTable.state.addresses.map((address) => (0, compat_1.fromLegacyPublicKey)(address)),
123
+ }), (tx) => (0, kit_1.addSignersToTransactionMessage)(signers, tx)));
125
124
  };
125
+ const addSignaturesToExistingTransaction = (transaction, signerKeys) => (0, kit_1.partiallySignTransaction)(signerKeys, transaction instanceof web3_js_1.VersionedTransaction
126
+ ? (0, compat_1.fromVersionedTransaction)(transaction) // VersionedTransaction has a lifetime so it's fine to cast it so we can call partiallySignTransaction
127
+ : transaction);
126
128
  const getSignerKeys = async (sessionKey, extraSigners) => {
127
129
  const extraSignerKeys = extraSigners === undefined
128
130
  ? []
@@ -151,20 +153,24 @@ const sponsorAndSendResponseSchema = zod_1.z
151
153
  ? TransactionResult.Success(data.signature)
152
154
  : TransactionResult.Failed(data.signature, data.error);
153
155
  });
154
- const getSponsor = async (options, domain) => {
155
- if (options.sponsor === undefined) {
156
+ const getSponsor = async (options, sponsorCache, domain) => {
157
+ const value = sponsorCache.get(domain);
158
+ if (value === undefined) {
156
159
  const url = new URL("/api/sponsor_pubkey", options.paymaster ?? DEFAULT_PAYMASTER[options.network]);
157
160
  url.searchParams.set("domain", domain);
161
+ url.searchParams.set("index", "autoassign");
158
162
  const response = await fetch(url);
159
163
  if (response.status === 200) {
160
- return new web3_js_1.PublicKey(zod_1.z.string().parse(await response.text()));
164
+ const sponsor = new web3_js_1.PublicKey(zod_1.z.string().parse(await response.text()));
165
+ sponsorCache.set(domain, sponsor);
166
+ return sponsor;
161
167
  }
162
168
  else {
163
169
  throw new PaymasterResponseError(response.status, await response.text());
164
170
  }
165
171
  }
166
172
  else {
167
- return options.sponsor;
173
+ return value;
168
174
  }
169
175
  };
170
176
  const getAddressLookupTable = async (connection, addressLookupTableCache, addressLookupTableAddress) => {
package/cjs/context.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Connection as Web3Connection } from "@solana/web3.js";
2
- import type { Connection } from "./connection.js";
2
+ import type { Connection, SendTransactionOptions as SendTransactionBaseOptions, TransactionOrInstructions } from "./connection.js";
3
+ export declare const SESSIONS_INTERNAL_PAYMASTER_DOMAIN = "sessions";
3
4
  export declare const createSessionContext: (options: {
4
5
  connection: Connection;
5
6
  defaultAddressLookupTableAddress?: string | undefined;
@@ -8,10 +9,14 @@ export declare const createSessionContext: (options: {
8
9
  chainId: string;
9
10
  domain: string;
10
11
  payer: import("@solana/web3.js").PublicKey;
12
+ internalPayer: import("@solana/web3.js").PublicKey;
11
13
  getSolanaConnection: () => Promise<Web3Connection>;
12
14
  connection: Web3Connection;
13
15
  rpc: import("@solana/kit").Rpc<import("@solana/kit").RequestAirdropApi & import("@solana/kit").GetAccountInfoApi & import("@solana/kit").GetBalanceApi & import("@solana/kit").GetBlockApi & import("@solana/kit").GetBlockCommitmentApi & import("@solana/kit").GetBlockHeightApi & import("@solana/kit").GetBlockProductionApi & import("@solana/kit").GetBlocksApi & import("@solana/kit").GetBlocksWithLimitApi & import("@solana/kit").GetBlockTimeApi & import("@solana/kit").GetClusterNodesApi & import("@solana/kit").GetEpochInfoApi & import("@solana/kit").GetEpochScheduleApi & import("@solana/kit").GetFeeForMessageApi & import("@solana/kit").GetFirstAvailableBlockApi & import("@solana/kit").GetGenesisHashApi & import("@solana/kit").GetHealthApi & import("@solana/kit").GetHighestSnapshotSlotApi & import("@solana/kit").GetIdentityApi & import("@solana/kit").GetInflationGovernorApi & import("@solana/kit").GetInflationRateApi & import("@solana/kit").GetInflationRewardApi & import("@solana/kit").GetLargestAccountsApi & import("@solana/kit").GetLatestBlockhashApi & import("@solana/kit").GetLeaderScheduleApi & import("@solana/kit").GetMaxRetransmitSlotApi & import("@solana/kit").GetMaxShredInsertSlotApi & import("@solana/kit").GetMinimumBalanceForRentExemptionApi & import("@solana/kit").GetMultipleAccountsApi & import("@solana/kit").GetProgramAccountsApi & import("@solana/kit").GetRecentPerformanceSamplesApi & import("@solana/kit").GetRecentPrioritizationFeesApi & import("@solana/kit").GetSignaturesForAddressApi & import("@solana/kit").GetSignatureStatusesApi & import("@solana/kit").GetSlotApi & import("@solana/kit").GetSlotLeaderApi & import("@solana/kit").GetSlotLeadersApi & import("@solana/kit").GetStakeMinimumDelegationApi & import("@solana/kit").GetSupplyApi & import("@solana/kit").GetTokenAccountBalanceApi & import("@solana/kit").GetTokenAccountsByDelegateApi & import("@solana/kit").GetTokenAccountsByOwnerApi & import("@solana/kit").GetTokenLargestAccountsApi & import("@solana/kit").GetTokenSupplyApi & import("@solana/kit").GetTransactionApi & import("@solana/kit").GetTransactionCountApi & import("@solana/kit").GetVersionApi & import("@solana/kit").GetVoteAccountsApi & import("@solana/kit").IsBlockhashValidApi & import("@solana/kit").MinimumLedgerSlotApi & import("@solana/kit").SendTransactionApi & import("@solana/kit").SimulateTransactionApi>;
14
16
  network: import("./connection.js").Network;
15
- sendTransaction: (sessionKey: CryptoKeyPair | undefined, instructions: Parameters<typeof options.connection.sendToPaymaster>[3], extraConfig?: Parameters<typeof options.connection.sendToPaymaster>[4]) => Promise<import("./connection.js").TransactionResult>;
17
+ sendTransaction: (sessionKey: CryptoKeyPair | undefined, instructions: TransactionOrInstructions, sendTxOptions?: SendTransactionOptions) => Promise<import("./connection.js").TransactionResult>;
16
18
  }>;
19
+ export type SendTransactionOptions = SendTransactionBaseOptions & {
20
+ paymasterDomain?: string | undefined;
21
+ };
17
22
  export type SessionContext = Awaited<ReturnType<typeof createSessionContext>>;
package/cjs/context.js CHANGED
@@ -1,26 +1,31 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createSessionContext = void 0;
3
+ exports.createSessionContext = exports.SESSIONS_INTERNAL_PAYMASTER_DOMAIN = void 0;
4
4
  const anchor_1 = require("@coral-xyz/anchor");
5
5
  const sessions_idls_1 = require("@fogo/sessions-idls");
6
6
  const web3_js_1 = require("@solana/web3.js");
7
7
  // eslint-disable-next-line unicorn/no-typeof-undefined
8
8
  const IS_BROWSER = typeof globalThis.window !== "undefined";
9
+ exports.SESSIONS_INTERNAL_PAYMASTER_DOMAIN = "sessions";
9
10
  const createSessionContext = async (options) => {
10
11
  const domain = getDomain(options.domain);
11
- const sponsor = await options.connection.getSponsor(domain);
12
+ const [sponsor, internalSponsor] = await Promise.all([
13
+ options.connection.getSponsor(domain),
14
+ options.connection.getSponsor(exports.SESSIONS_INTERNAL_PAYMASTER_DOMAIN),
15
+ ]);
12
16
  return {
13
17
  chainId: await fetchChainId(options.connection.connection),
14
18
  domain: getDomain(options.domain),
15
19
  payer: sponsor,
20
+ internalPayer: internalSponsor,
16
21
  getSolanaConnection: options.connection.getSolanaConnection,
17
22
  connection: options.connection.connection,
18
23
  rpc: options.connection.rpc,
19
24
  network: options.connection.network,
20
- sendTransaction: (sessionKey, instructions, extraConfig) => options.connection.sendToPaymaster(domain, sponsor, sessionKey, instructions, {
21
- addressLookupTable: extraConfig?.addressLookupTable ??
25
+ sendTransaction: (sessionKey, instructions, sendTxOptions) => options.connection.sendToPaymaster(sendTxOptions?.paymasterDomain ?? domain, sessionKey, instructions, {
26
+ ...sendTxOptions,
27
+ addressLookupTable: sendTxOptions?.addressLookupTable ??
22
28
  options.defaultAddressLookupTableAddress,
23
- extraSigners: extraConfig?.extraSigners,
24
29
  }),
25
30
  };
26
31
  };
package/cjs/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
- import type { BaseWalletAdapter, MessageSignerWalletAdapterProps } from "@solana/wallet-adapter-base";
1
+ import type { BaseSignerWalletAdapter, MessageSignerWalletAdapterProps } from "@solana/wallet-adapter-base";
2
2
  import type { TransactionError } from "@solana/web3.js";
3
3
  import { Connection, PublicKey } from "@solana/web3.js";
4
4
  import type { Chain } from "@wormhole-foundation/sdk";
5
5
  import BN from "bn.js";
6
6
  import { z } from "zod";
7
- import type { TransactionResult } from "./connection.js";
8
- import type { SessionContext } from "./context.js";
9
- export { type SessionContext, createSessionContext } from "./context.js";
10
- export { type TransactionResult, type Connection, Network, TransactionResultType, createSessionConnection, } from "./connection.js";
7
+ import type { TransactionOrInstructions, TransactionResult } from "./connection.js";
8
+ import type { SendTransactionOptions, SessionContext } from "./context.js";
9
+ export { type SessionContext, type SendTransactionOptions, createSessionContext, } from "./context.js";
10
+ export { type TransactionResult, type Connection, type TransactionOrInstructions, Network, TransactionResultType, createSessionConnection, } from "./connection.js";
11
11
  type EstablishSessionOptions = {
12
12
  context: SessionContext;
13
13
  walletPublicKey: PublicKey;
@@ -1307,7 +1307,7 @@ export type Session = {
1307
1307
  sessionKey: CryptoKeyPair;
1308
1308
  walletPublicKey: PublicKey;
1309
1309
  payer: PublicKey;
1310
- sendTransaction: (instructions: Parameters<SessionContext["sendTransaction"]>[1]) => Promise<TransactionResult>;
1310
+ sendTransaction: (instructions: TransactionOrInstructions, extraConfig?: SendTransactionOptions) => Promise<TransactionResult>;
1311
1311
  sessionInfo: NonNullable<z.infer<typeof sessionInfoSchema>>;
1312
1312
  };
1313
1313
  export declare const getTransferFee: (context: SessionContext) => Promise<{
@@ -1359,7 +1359,7 @@ export declare const bridgeOut: (options: SendBridgeOutOptions) => Promise<Trans
1359
1359
  type SendBridgeInOptions = {
1360
1360
  context: SessionContext;
1361
1361
  walletPublicKey: PublicKey;
1362
- solanaWallet: BaseWalletAdapter;
1362
+ solanaWallet: BaseSignerWalletAdapter;
1363
1363
  amount: bigint;
1364
1364
  fromToken: WormholeToken & {
1365
1365
  chain: "Solana";
package/cjs/index.js CHANGED
@@ -24,9 +24,10 @@ const bn_js_1 = __importDefault(require("bn.js"));
24
24
  const bs58_1 = __importDefault(require("bs58"));
25
25
  const zod_1 = require("zod");
26
26
  const connection_js_1 = require("./connection.js");
27
+ const context_js_1 = require("./context.js");
27
28
  const crypto_js_1 = require("./crypto.js");
28
- var context_js_1 = require("./context.js");
29
- Object.defineProperty(exports, "createSessionContext", { enumerable: true, get: function () { return context_js_1.createSessionContext; } });
29
+ var context_js_2 = require("./context.js");
30
+ Object.defineProperty(exports, "createSessionContext", { enumerable: true, get: function () { return context_js_2.createSessionContext; } });
30
31
  var connection_js_2 = require("./connection.js");
31
32
  Object.defineProperty(exports, "Network", { enumerable: true, get: function () { return connection_js_2.Network; } });
32
33
  Object.defineProperty(exports, "TransactionResultType", { enumerable: true, get: function () { return connection_js_2.TransactionResultType; } });
@@ -65,16 +66,13 @@ const establishSession = async (options) => {
65
66
  buildIntentInstruction(options, sessionKey, tokenInfo),
66
67
  buildStartSessionInstruction(options, sessionKey, tokenInfo),
67
68
  ]);
68
- return sendSessionEstablishTransaction(options, sessionKey, [
69
- ...buildCreateAssociatedTokenAccountInstructions(options, tokenInfo),
70
- intentInstruction,
71
- startSessionInstruction,
72
- ], options.sessionEstablishmentLookupTable);
69
+ return sendSessionEstablishTransaction(options, sessionKey, [intentInstruction, startSessionInstruction], options.sessionEstablishmentLookupTable);
73
70
  }
74
71
  };
75
72
  exports.establishSession = establishSession;
76
73
  const sendSessionEstablishTransaction = async (options, sessionKey, instructions, sessionEstablishmentLookupTable) => {
77
74
  const result = await options.context.sendTransaction(sessionKey, instructions, {
75
+ variation: "Session Establishment",
78
76
  addressLookupTable: sessionEstablishmentLookupTable ??
79
77
  SESSION_ESTABLISHMENT_LOOKUP_TABLE_ADDRESS[options.context.network],
80
78
  });
@@ -104,9 +102,9 @@ const revokeSession = async (options) => {
104
102
  session: options.session.sessionPublicKey,
105
103
  })
106
104
  .instruction();
107
- return options.context.sendTransaction(options.session.sessionKey, [
108
- instruction,
109
- ]);
105
+ return options.context.sendTransaction(options.session.sessionKey, [instruction], {
106
+ variation: "Session Revocation",
107
+ });
110
108
  }
111
109
  else {
112
110
  return;
@@ -132,7 +130,7 @@ const createSession = async (context, walletPublicKey, sessionKey) => {
132
130
  walletPublicKey,
133
131
  sessionKey,
134
132
  payer: context.payer,
135
- sendTransaction: (instructions) => context.sendTransaction(sessionKey, instructions),
133
+ sendTransaction: (instructions, extraConfig) => context.sendTransaction(sessionKey, instructions, extraConfig),
136
134
  sessionInfo,
137
135
  };
138
136
  };
@@ -435,7 +433,6 @@ const amountToString = (amount, decimals) => {
435
433
  ...(decimalTruncated === "" ? [] : [".", decimalTruncated]),
436
434
  ].join("");
437
435
  };
438
- const buildCreateAssociatedTokenAccountInstructions = (options, tokens) => tokens.map(({ mint }) => (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(options.context.payer, (0, spl_token_1.getAssociatedTokenAddressSync)(mint, options.walletPublicKey), options.walletPublicKey, mint));
439
436
  const getDomainRecordAddress = (domain) => {
440
437
  const hash = (0, sha2_1.sha256)(domain);
441
438
  return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("domain-record"), hash], new web3_js_1.PublicKey(sessions_idls_1.DomainRegistryIdl.address))[0];
@@ -535,7 +532,7 @@ const getFee = async (context) => {
535
532
  mint: (0, umi_1.publicKey)(usdcMintAddress),
536
533
  })[0],
537
534
  mint: usdcMint,
538
- symbolOrMint: context.network === connection_js_1.Network.Mainnet ? "USDC.s" : "USDC",
535
+ symbolOrMint: "USDC.s",
539
536
  decimals: USDC_DECIMALS,
540
537
  fee: {
541
538
  intrachainTransfer: BigInt(feeConfig.intrachainTransferFee.toString()),
@@ -565,12 +562,16 @@ const sendTransfer = async (options) => {
565
562
  feeSource: (0, spl_token_1.getAssociatedTokenAddressSync)(options.feeConfig.mint, options.walletPublicKey),
566
563
  mint: options.mint,
567
564
  source: sourceAta,
568
- sponsor: options.context.payer,
565
+ sponsor: options.context.internalPayer,
566
+ metadata:
569
567
  // eslint-disable-next-line unicorn/no-null
570
- metadata: symbol === undefined ? null : new web3_js_1.PublicKey(metadataAddress),
568
+ symbol === undefined ? null : new web3_js_1.PublicKey(metadataAddress),
571
569
  })
572
570
  .instruction(),
573
- ]);
571
+ ], {
572
+ variation: "Intent Transfer",
573
+ paymasterDomain: context_js_1.SESSIONS_INTERNAL_PAYMASTER_DOMAIN,
574
+ });
574
575
  };
575
576
  exports.sendTransfer = sendTransfer;
576
577
  const buildTransferIntentInstruction = async (program, options, symbol, feeToken, feeAmount) => {
@@ -601,7 +602,7 @@ const buildTransferIntentInstruction = async (program, options, symbol, feeToken
601
602
  const BRIDGE_OUT_MESSAGE_HEADER = `Fogo Bridge Transfer:
602
603
  Signing this intent will bridge out the tokens as described below.
603
604
  `;
604
- const BRIDGE_OUT_CUS = 220_000;
605
+ const BRIDGE_OUT_CUS = 240_000;
605
606
  const bridgeOut = async (options) => {
606
607
  const { wh, route, transferRequest, transferParams, decimals } = await buildWormholeTransfer(options, options.context.connection);
607
608
  // @ts-expect-error the wormhole client types are incorrect and do not
@@ -622,10 +623,10 @@ const bridgeOut = async (options) => {
622
623
  program.methods
623
624
  .bridgeNttTokens({
624
625
  payDestinationAtaRent: !destinationAtaExists,
625
- signedQuoteBytes: Buffer.from(quote.signedQuote),
626
+ signedQuoteBytes: [...quote.signedQuote],
626
627
  })
627
628
  .accounts({
628
- sponsor: options.context.payer,
629
+ sponsor: options.context.internalPayer,
629
630
  mint: options.fromToken.mint,
630
631
  metadata: metadata?.symbol === undefined
631
632
  ? // eslint-disable-next-line unicorn/no-null
@@ -643,6 +644,8 @@ const bridgeOut = async (options) => {
643
644
  web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: BRIDGE_OUT_CUS }),
644
645
  ...instructions,
645
646
  ], {
647
+ variation: "Intent NTT Bridge",
648
+ paymasterDomain: context_js_1.SESSIONS_INTERNAL_PAYMASTER_DOMAIN,
646
649
  extraSigners: [outboxItem],
647
650
  addressLookupTable: BRIDGING_ADDRESS_LOOKUP_TABLE[options.context.network]?.[options.fromToken.mint.toBase58()],
648
651
  });
@@ -727,12 +730,17 @@ const bridgeIn = async (options) => {
727
730
  return await sdk_1.routes.checkAndCompleteTransfer(route, await route.initiate(transferRequest, {
728
731
  address: () => options.walletPublicKey.toBase58(),
729
732
  chain: () => "Solana",
730
- signAndSend: (transactions) => Promise.all(transactions.map(({ transaction }) => options.solanaWallet.sendTransaction(
731
- // Hooray for Wormhole's incomplete typing eh?
732
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
733
- transaction.transaction, solanaConnection,
734
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
735
- { signers: transaction.signers }))),
733
+ sign: (transactions) => Promise.all(transactions.map(async ({ transaction }) => {
734
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
735
+ const signedTx = await options.solanaWallet.signTransaction(
736
+ // Hooray for Wormhole's incomplete typing eh?
737
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
738
+ transaction.transaction);
739
+ // Hooray for Wormhole's incomplete typing eh?
740
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
741
+ signedTx.sign(transaction.signers);
742
+ return signedTx.serialize();
743
+ })),
736
744
  }, quote, sdk_1.Wormhole.chainAddress("Fogo", options.walletPublicKey.toBase58())));
737
745
  }
738
746
  else {
@@ -1,4 +1,4 @@
1
- import type { Transaction, Instruction, TransactionWithLifetime } from "@solana/kit";
1
+ import type { Transaction, Instruction, TransactionWithLifetime, Rpc, GetLatestBlockhashApi } from "@solana/kit";
2
2
  import type { TransactionError } from "@solana/web3.js";
3
3
  import { Keypair, Connection as Web3Connection, TransactionInstruction, VersionedTransaction, PublicKey } from "@solana/web3.js";
4
4
  export declare enum Network {
@@ -33,15 +33,18 @@ export declare const createSessionConnection: (options: {
33
33
  sendToPaymaster: (transaction: Transaction) => Promise<TransactionResult>;
34
34
  sponsor: PublicKey;
35
35
  })) => {
36
- rpc: import("@solana/kit").Rpc<import("@solana/kit").RequestAirdropApi & import("@solana/kit").GetAccountInfoApi & import("@solana/kit").GetBalanceApi & import("@solana/kit").GetBlockApi & import("@solana/kit").GetBlockCommitmentApi & import("@solana/kit").GetBlockHeightApi & import("@solana/kit").GetBlockProductionApi & import("@solana/kit").GetBlocksApi & import("@solana/kit").GetBlocksWithLimitApi & import("@solana/kit").GetBlockTimeApi & import("@solana/kit").GetClusterNodesApi & import("@solana/kit").GetEpochInfoApi & import("@solana/kit").GetEpochScheduleApi & import("@solana/kit").GetFeeForMessageApi & import("@solana/kit").GetFirstAvailableBlockApi & import("@solana/kit").GetGenesisHashApi & import("@solana/kit").GetHealthApi & import("@solana/kit").GetHighestSnapshotSlotApi & import("@solana/kit").GetIdentityApi & import("@solana/kit").GetInflationGovernorApi & import("@solana/kit").GetInflationRateApi & import("@solana/kit").GetInflationRewardApi & import("@solana/kit").GetLargestAccountsApi & import("@solana/kit").GetLatestBlockhashApi & import("@solana/kit").GetLeaderScheduleApi & import("@solana/kit").GetMaxRetransmitSlotApi & import("@solana/kit").GetMaxShredInsertSlotApi & import("@solana/kit").GetMinimumBalanceForRentExemptionApi & import("@solana/kit").GetMultipleAccountsApi & import("@solana/kit").GetProgramAccountsApi & import("@solana/kit").GetRecentPerformanceSamplesApi & import("@solana/kit").GetRecentPrioritizationFeesApi & import("@solana/kit").GetSignaturesForAddressApi & import("@solana/kit").GetSignatureStatusesApi & import("@solana/kit").GetSlotApi & import("@solana/kit").GetSlotLeaderApi & import("@solana/kit").GetSlotLeadersApi & import("@solana/kit").GetStakeMinimumDelegationApi & import("@solana/kit").GetSupplyApi & import("@solana/kit").GetTokenAccountBalanceApi & import("@solana/kit").GetTokenAccountsByDelegateApi & import("@solana/kit").GetTokenAccountsByOwnerApi & import("@solana/kit").GetTokenLargestAccountsApi & import("@solana/kit").GetTokenSupplyApi & import("@solana/kit").GetTransactionApi & import("@solana/kit").GetTransactionCountApi & import("@solana/kit").GetVersionApi & import("@solana/kit").GetVoteAccountsApi & import("@solana/kit").IsBlockhashValidApi & import("@solana/kit").MinimumLedgerSlotApi & import("@solana/kit").SendTransactionApi & import("@solana/kit").SimulateTransactionApi>;
36
+ rpc: Rpc<import("@solana/kit").RequestAirdropApi & import("@solana/kit").GetAccountInfoApi & import("@solana/kit").GetBalanceApi & import("@solana/kit").GetBlockApi & import("@solana/kit").GetBlockCommitmentApi & import("@solana/kit").GetBlockHeightApi & import("@solana/kit").GetBlockProductionApi & import("@solana/kit").GetBlocksApi & import("@solana/kit").GetBlocksWithLimitApi & import("@solana/kit").GetBlockTimeApi & import("@solana/kit").GetClusterNodesApi & import("@solana/kit").GetEpochInfoApi & import("@solana/kit").GetEpochScheduleApi & import("@solana/kit").GetFeeForMessageApi & import("@solana/kit").GetFirstAvailableBlockApi & import("@solana/kit").GetGenesisHashApi & import("@solana/kit").GetHealthApi & import("@solana/kit").GetHighestSnapshotSlotApi & import("@solana/kit").GetIdentityApi & import("@solana/kit").GetInflationGovernorApi & import("@solana/kit").GetInflationRateApi & import("@solana/kit").GetInflationRewardApi & import("@solana/kit").GetLargestAccountsApi & GetLatestBlockhashApi & import("@solana/kit").GetLeaderScheduleApi & import("@solana/kit").GetMaxRetransmitSlotApi & import("@solana/kit").GetMaxShredInsertSlotApi & import("@solana/kit").GetMinimumBalanceForRentExemptionApi & import("@solana/kit").GetMultipleAccountsApi & import("@solana/kit").GetProgramAccountsApi & import("@solana/kit").GetRecentPerformanceSamplesApi & import("@solana/kit").GetRecentPrioritizationFeesApi & import("@solana/kit").GetSignaturesForAddressApi & import("@solana/kit").GetSignatureStatusesApi & import("@solana/kit").GetSlotApi & import("@solana/kit").GetSlotLeaderApi & import("@solana/kit").GetSlotLeadersApi & import("@solana/kit").GetStakeMinimumDelegationApi & import("@solana/kit").GetSupplyApi & import("@solana/kit").GetTokenAccountBalanceApi & import("@solana/kit").GetTokenAccountsByDelegateApi & import("@solana/kit").GetTokenAccountsByOwnerApi & import("@solana/kit").GetTokenLargestAccountsApi & import("@solana/kit").GetTokenSupplyApi & import("@solana/kit").GetTransactionApi & import("@solana/kit").GetTransactionCountApi & import("@solana/kit").GetVersionApi & import("@solana/kit").GetVoteAccountsApi & import("@solana/kit").IsBlockhashValidApi & import("@solana/kit").MinimumLedgerSlotApi & import("@solana/kit").SendTransactionApi & import("@solana/kit").SimulateTransactionApi>;
37
37
  connection: Web3Connection;
38
38
  network: Network;
39
39
  getSolanaConnection: () => Promise<Web3Connection>;
40
- sendToPaymaster: (domain: string, sponsor: PublicKey, sessionKey: CryptoKeyPair | undefined, instructions: (TransactionInstruction | Instruction)[] | VersionedTransaction | (Transaction & TransactionWithLifetime), extraConfig?: {
41
- addressLookupTable?: string | undefined;
42
- extraSigners?: (CryptoKeyPair | Keypair)[] | undefined;
43
- }) => Promise<TransactionResult>;
40
+ sendToPaymaster: (domain: string, sessionKey: CryptoKeyPair | undefined, instructions: TransactionOrInstructions, extraConfig?: SendTransactionOptions) => Promise<TransactionResult>;
44
41
  getSponsor: (domain: string) => Promise<PublicKey>;
45
42
  };
43
+ export type TransactionOrInstructions = (TransactionInstruction | Instruction)[] | VersionedTransaction | (Transaction & TransactionWithLifetime);
44
+ export type SendTransactionOptions = {
45
+ variation?: string | undefined;
46
+ addressLookupTable?: string | undefined;
47
+ extraSigners?: (CryptoKeyPair | Keypair)[] | undefined;
48
+ };
46
49
  export type Connection = ReturnType<typeof createSessionConnection>;
47
50
  export {};
package/esm/connection.js CHANGED
@@ -36,17 +36,14 @@ export const createSessionConnection = (options) => {
36
36
  const rpc = createSolanaRpc(rpcUrl);
37
37
  const connection = new Web3Connection(rpcUrl, "confirmed");
38
38
  const addressLookupTableCache = new Map();
39
+ const sponsorCache = new Map();
39
40
  return {
40
41
  rpc,
41
42
  connection,
42
43
  network: options.network,
43
44
  getSolanaConnection: createSolanaConnectionGetter(options.network),
44
- sendToPaymaster: async (domain, sponsor, sessionKey, instructions, extraConfig) => {
45
- const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
46
- const transaction = await buildTransaction(connection, latestBlockhash, sessionKey, sponsor, instructions, addressLookupTableCache, extraConfig);
47
- return sendToPaymaster(options, domain, transaction);
48
- },
49
- getSponsor: (domain) => getSponsor(options, domain),
45
+ sendToPaymaster: async (domain, sessionKey, instructions, extraConfig) => sendToPaymaster({ ...options, rpc, connection, addressLookupTableCache, sponsorCache }, domain, sessionKey, instructions, extraConfig),
46
+ getSponsor: (domain) => getSponsor(options, sponsorCache, domain),
50
47
  };
51
48
  };
52
49
  const createSolanaConnectionGetter = (network) => {
@@ -71,10 +68,17 @@ const NETWORK_TO_QUERY_PARAM = {
71
68
  [Network.Mainnet]: "mainnet",
72
69
  [Network.Testnet]: "testnet",
73
70
  };
74
- const sendToPaymaster = async (options, domain, transaction) => {
75
- if (options.sendToPaymaster === undefined) {
76
- const url = new URL("/api/sponsor_and_send", options.paymaster ?? DEFAULT_PAYMASTER[options.network]);
71
+ const sendToPaymaster = async (connection, domain, sessionKey, instructions, extraConfig) => {
72
+ const signerKeys = await getSignerKeys(sessionKey, extraConfig?.extraSigners);
73
+ const transaction = Array.isArray(instructions)
74
+ ? await buildTransaction(connection, domain, signerKeys, instructions, extraConfig)
75
+ : await addSignaturesToExistingTransaction(instructions, signerKeys);
76
+ if (connection.sendToPaymaster === undefined) {
77
+ const url = new URL("/api/sponsor_and_send", connection.paymaster ?? DEFAULT_PAYMASTER[connection.network]);
77
78
  url.searchParams.set("domain", domain);
79
+ if (extraConfig?.variation !== undefined) {
80
+ url.searchParams.set("variation", extraConfig.variation);
81
+ }
78
82
  const response = await fetch(url, {
79
83
  method: "POST",
80
84
  headers: {
@@ -92,33 +96,31 @@ const sendToPaymaster = async (options, domain, transaction) => {
92
96
  }
93
97
  }
94
98
  else {
95
- return options.sendToPaymaster(transaction);
99
+ return connection.sendToPaymaster(transaction);
96
100
  }
97
101
  };
98
- const buildTransaction = async (connection, latestBlockhash, sessionKey, sponsor, instructions, addressLookupTableCache, extraConfig) => {
99
- const [signerKeys, addressLookupTable] = await Promise.all([
100
- getSignerKeys(sessionKey, extraConfig?.extraSigners),
102
+ const buildTransaction = async (connection, domain, signerKeys, instructions, extraConfig) => {
103
+ const [{ value: latestBlockhash }, sponsor, addressLookupTable, signers] = await Promise.all([
104
+ connection.rpc.getLatestBlockhash().send(),
105
+ connection.sponsor === undefined
106
+ ? getSponsor(connection, connection.sponsorCache, domain)
107
+ : Promise.resolve(connection.sponsor),
101
108
  extraConfig?.addressLookupTable === undefined
102
109
  ? Promise.resolve(undefined)
103
- : getAddressLookupTable(connection, addressLookupTableCache, extraConfig.addressLookupTable),
110
+ : getAddressLookupTable(connection.connection, connection.addressLookupTableCache, extraConfig.addressLookupTable),
111
+ Promise.all(signerKeys.map((signer) => createSignerFromKeyPair(signer))),
104
112
  ]);
105
- if (Array.isArray(instructions)) {
106
- const signers = await Promise.all(signerKeys.map((signer) => createSignerFromKeyPair(signer)));
107
- return partiallySignTransactionMessageWithSigners(pipe(createTransactionMessage({ version: 0 }), (tx) => setTransactionMessageFeePayer(fromLegacyPublicKey(sponsor), tx), (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), (tx) => appendTransactionMessageInstructions(instructions.map((instruction) => instruction instanceof TransactionInstruction
108
- ? fromLegacyTransactionInstruction(instruction)
109
- : instruction), tx), (tx) => addressLookupTable === undefined
110
- ? tx
111
- : compressTransactionMessageUsingAddressLookupTables(tx, {
112
- [fromLegacyPublicKey(addressLookupTable.key)]: addressLookupTable.state.addresses.map((address) => fromLegacyPublicKey(address)),
113
- }), (tx) => addSignersToTransactionMessage(signers, tx)));
114
- }
115
- else {
116
- const tx = instructions instanceof VersionedTransaction
117
- ? fromVersionedTransaction(instructions) // VersionedTransaction has a lifetime so it's fine to cast it so we can call partiallySignTransaction
118
- : instructions;
119
- return partiallySignTransaction(signerKeys, tx);
120
- }
113
+ return partiallySignTransactionMessageWithSigners(pipe(createTransactionMessage({ version: 0 }), (tx) => setTransactionMessageFeePayer(fromLegacyPublicKey(sponsor), tx), (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), (tx) => appendTransactionMessageInstructions(instructions.map((instruction) => instruction instanceof TransactionInstruction
114
+ ? fromLegacyTransactionInstruction(instruction)
115
+ : instruction), tx), (tx) => addressLookupTable === undefined
116
+ ? tx
117
+ : compressTransactionMessageUsingAddressLookupTables(tx, {
118
+ [fromLegacyPublicKey(addressLookupTable.key)]: addressLookupTable.state.addresses.map((address) => fromLegacyPublicKey(address)),
119
+ }), (tx) => addSignersToTransactionMessage(signers, tx)));
121
120
  };
121
+ const addSignaturesToExistingTransaction = (transaction, signerKeys) => partiallySignTransaction(signerKeys, transaction instanceof VersionedTransaction
122
+ ? fromVersionedTransaction(transaction) // VersionedTransaction has a lifetime so it's fine to cast it so we can call partiallySignTransaction
123
+ : transaction);
122
124
  const getSignerKeys = async (sessionKey, extraSigners) => {
123
125
  const extraSignerKeys = extraSigners === undefined
124
126
  ? []
@@ -147,20 +149,24 @@ const sponsorAndSendResponseSchema = z
147
149
  ? TransactionResult.Success(data.signature)
148
150
  : TransactionResult.Failed(data.signature, data.error);
149
151
  });
150
- const getSponsor = async (options, domain) => {
151
- if (options.sponsor === undefined) {
152
+ const getSponsor = async (options, sponsorCache, domain) => {
153
+ const value = sponsorCache.get(domain);
154
+ if (value === undefined) {
152
155
  const url = new URL("/api/sponsor_pubkey", options.paymaster ?? DEFAULT_PAYMASTER[options.network]);
153
156
  url.searchParams.set("domain", domain);
157
+ url.searchParams.set("index", "autoassign");
154
158
  const response = await fetch(url);
155
159
  if (response.status === 200) {
156
- return new PublicKey(z.string().parse(await response.text()));
160
+ const sponsor = new PublicKey(z.string().parse(await response.text()));
161
+ sponsorCache.set(domain, sponsor);
162
+ return sponsor;
157
163
  }
158
164
  else {
159
165
  throw new PaymasterResponseError(response.status, await response.text());
160
166
  }
161
167
  }
162
168
  else {
163
- return options.sponsor;
169
+ return value;
164
170
  }
165
171
  };
166
172
  const getAddressLookupTable = async (connection, addressLookupTableCache, addressLookupTableAddress) => {
package/esm/context.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Connection as Web3Connection } from "@solana/web3.js";
2
- import type { Connection } from "./connection.js";
2
+ import type { Connection, SendTransactionOptions as SendTransactionBaseOptions, TransactionOrInstructions } from "./connection.js";
3
+ export declare const SESSIONS_INTERNAL_PAYMASTER_DOMAIN = "sessions";
3
4
  export declare const createSessionContext: (options: {
4
5
  connection: Connection;
5
6
  defaultAddressLookupTableAddress?: string | undefined;
@@ -8,10 +9,14 @@ export declare const createSessionContext: (options: {
8
9
  chainId: string;
9
10
  domain: string;
10
11
  payer: import("@solana/web3.js").PublicKey;
12
+ internalPayer: import("@solana/web3.js").PublicKey;
11
13
  getSolanaConnection: () => Promise<Web3Connection>;
12
14
  connection: Web3Connection;
13
15
  rpc: import("@solana/kit").Rpc<import("@solana/kit").RequestAirdropApi & import("@solana/kit").GetAccountInfoApi & import("@solana/kit").GetBalanceApi & import("@solana/kit").GetBlockApi & import("@solana/kit").GetBlockCommitmentApi & import("@solana/kit").GetBlockHeightApi & import("@solana/kit").GetBlockProductionApi & import("@solana/kit").GetBlocksApi & import("@solana/kit").GetBlocksWithLimitApi & import("@solana/kit").GetBlockTimeApi & import("@solana/kit").GetClusterNodesApi & import("@solana/kit").GetEpochInfoApi & import("@solana/kit").GetEpochScheduleApi & import("@solana/kit").GetFeeForMessageApi & import("@solana/kit").GetFirstAvailableBlockApi & import("@solana/kit").GetGenesisHashApi & import("@solana/kit").GetHealthApi & import("@solana/kit").GetHighestSnapshotSlotApi & import("@solana/kit").GetIdentityApi & import("@solana/kit").GetInflationGovernorApi & import("@solana/kit").GetInflationRateApi & import("@solana/kit").GetInflationRewardApi & import("@solana/kit").GetLargestAccountsApi & import("@solana/kit").GetLatestBlockhashApi & import("@solana/kit").GetLeaderScheduleApi & import("@solana/kit").GetMaxRetransmitSlotApi & import("@solana/kit").GetMaxShredInsertSlotApi & import("@solana/kit").GetMinimumBalanceForRentExemptionApi & import("@solana/kit").GetMultipleAccountsApi & import("@solana/kit").GetProgramAccountsApi & import("@solana/kit").GetRecentPerformanceSamplesApi & import("@solana/kit").GetRecentPrioritizationFeesApi & import("@solana/kit").GetSignaturesForAddressApi & import("@solana/kit").GetSignatureStatusesApi & import("@solana/kit").GetSlotApi & import("@solana/kit").GetSlotLeaderApi & import("@solana/kit").GetSlotLeadersApi & import("@solana/kit").GetStakeMinimumDelegationApi & import("@solana/kit").GetSupplyApi & import("@solana/kit").GetTokenAccountBalanceApi & import("@solana/kit").GetTokenAccountsByDelegateApi & import("@solana/kit").GetTokenAccountsByOwnerApi & import("@solana/kit").GetTokenLargestAccountsApi & import("@solana/kit").GetTokenSupplyApi & import("@solana/kit").GetTransactionApi & import("@solana/kit").GetTransactionCountApi & import("@solana/kit").GetVersionApi & import("@solana/kit").GetVoteAccountsApi & import("@solana/kit").IsBlockhashValidApi & import("@solana/kit").MinimumLedgerSlotApi & import("@solana/kit").SendTransactionApi & import("@solana/kit").SimulateTransactionApi>;
14
16
  network: import("./connection.js").Network;
15
- sendTransaction: (sessionKey: CryptoKeyPair | undefined, instructions: Parameters<typeof options.connection.sendToPaymaster>[3], extraConfig?: Parameters<typeof options.connection.sendToPaymaster>[4]) => Promise<import("./connection.js").TransactionResult>;
17
+ sendTransaction: (sessionKey: CryptoKeyPair | undefined, instructions: TransactionOrInstructions, sendTxOptions?: SendTransactionOptions) => Promise<import("./connection.js").TransactionResult>;
16
18
  }>;
19
+ export type SendTransactionOptions = SendTransactionBaseOptions & {
20
+ paymasterDomain?: string | undefined;
21
+ };
17
22
  export type SessionContext = Awaited<ReturnType<typeof createSessionContext>>;
package/esm/context.js CHANGED
@@ -3,21 +3,26 @@ import { ChainIdProgram } from "@fogo/sessions-idls";
3
3
  import { Connection as Web3Connection, Keypair } from "@solana/web3.js";
4
4
  // eslint-disable-next-line unicorn/no-typeof-undefined
5
5
  const IS_BROWSER = typeof globalThis.window !== "undefined";
6
+ export const SESSIONS_INTERNAL_PAYMASTER_DOMAIN = "sessions";
6
7
  export const createSessionContext = async (options) => {
7
8
  const domain = getDomain(options.domain);
8
- const sponsor = await options.connection.getSponsor(domain);
9
+ const [sponsor, internalSponsor] = await Promise.all([
10
+ options.connection.getSponsor(domain),
11
+ options.connection.getSponsor(SESSIONS_INTERNAL_PAYMASTER_DOMAIN),
12
+ ]);
9
13
  return {
10
14
  chainId: await fetchChainId(options.connection.connection),
11
15
  domain: getDomain(options.domain),
12
16
  payer: sponsor,
17
+ internalPayer: internalSponsor,
13
18
  getSolanaConnection: options.connection.getSolanaConnection,
14
19
  connection: options.connection.connection,
15
20
  rpc: options.connection.rpc,
16
21
  network: options.connection.network,
17
- sendTransaction: (sessionKey, instructions, extraConfig) => options.connection.sendToPaymaster(domain, sponsor, sessionKey, instructions, {
18
- addressLookupTable: extraConfig?.addressLookupTable ??
22
+ sendTransaction: (sessionKey, instructions, sendTxOptions) => options.connection.sendToPaymaster(sendTxOptions?.paymasterDomain ?? domain, sessionKey, instructions, {
23
+ ...sendTxOptions,
24
+ addressLookupTable: sendTxOptions?.addressLookupTable ??
19
25
  options.defaultAddressLookupTableAddress,
20
- extraSigners: extraConfig?.extraSigners,
21
26
  }),
22
27
  };
23
28
  };
package/esm/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
- import type { BaseWalletAdapter, MessageSignerWalletAdapterProps } from "@solana/wallet-adapter-base";
1
+ import type { BaseSignerWalletAdapter, MessageSignerWalletAdapterProps } from "@solana/wallet-adapter-base";
2
2
  import type { TransactionError } from "@solana/web3.js";
3
3
  import { Connection, PublicKey } from "@solana/web3.js";
4
4
  import type { Chain } from "@wormhole-foundation/sdk";
5
5
  import BN from "bn.js";
6
6
  import { z } from "zod";
7
- import type { TransactionResult } from "./connection.js";
8
- import type { SessionContext } from "./context.js";
9
- export { type SessionContext, createSessionContext } from "./context.js";
10
- export { type TransactionResult, type Connection, Network, TransactionResultType, createSessionConnection, } from "./connection.js";
7
+ import type { TransactionOrInstructions, TransactionResult } from "./connection.js";
8
+ import type { SendTransactionOptions, SessionContext } from "./context.js";
9
+ export { type SessionContext, type SendTransactionOptions, createSessionContext, } from "./context.js";
10
+ export { type TransactionResult, type Connection, type TransactionOrInstructions, Network, TransactionResultType, createSessionConnection, } from "./connection.js";
11
11
  type EstablishSessionOptions = {
12
12
  context: SessionContext;
13
13
  walletPublicKey: PublicKey;
@@ -1307,7 +1307,7 @@ export type Session = {
1307
1307
  sessionKey: CryptoKeyPair;
1308
1308
  walletPublicKey: PublicKey;
1309
1309
  payer: PublicKey;
1310
- sendTransaction: (instructions: Parameters<SessionContext["sendTransaction"]>[1]) => Promise<TransactionResult>;
1310
+ sendTransaction: (instructions: TransactionOrInstructions, extraConfig?: SendTransactionOptions) => Promise<TransactionResult>;
1311
1311
  sessionInfo: NonNullable<z.infer<typeof sessionInfoSchema>>;
1312
1312
  };
1313
1313
  export declare const getTransferFee: (context: SessionContext) => Promise<{
@@ -1359,7 +1359,7 @@ export declare const bridgeOut: (options: SendBridgeOutOptions) => Promise<Trans
1359
1359
  type SendBridgeInOptions = {
1360
1360
  context: SessionContext;
1361
1361
  walletPublicKey: PublicKey;
1362
- solanaWallet: BaseWalletAdapter;
1362
+ solanaWallet: BaseSignerWalletAdapter;
1363
1363
  amount: bigint;
1364
1364
  fromToken: WormholeToken & {
1365
1365
  chain: "Solana";
package/esm/index.js CHANGED
@@ -6,7 +6,7 @@ import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
6
6
  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
- import { createAssociatedTokenAccountIdempotentInstruction, getAssociatedTokenAddressSync, getMint, } from "@solana/spl-token";
9
+ import { getAssociatedTokenAddressSync, getMint } from "@solana/spl-token";
10
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";
@@ -18,8 +18,9 @@ import BN from "bn.js";
18
18
  import bs58 from "bs58";
19
19
  import { z } from "zod";
20
20
  import { Network, TransactionResultType } from "./connection.js";
21
+ import { SESSIONS_INTERNAL_PAYMASTER_DOMAIN } from "./context.js";
21
22
  import { importKey, signMessageWithKey, verifyMessageWithKey, } from "./crypto.js";
22
- export { createSessionContext } from "./context.js";
23
+ export { createSessionContext, } from "./context.js";
23
24
  export { Network, TransactionResultType, createSessionConnection, } from "./connection.js";
24
25
  const MESSAGE_HEADER = `Fogo Sessions:
25
26
  Signing this intent will allow this app to interact with your on-chain balances. Please make sure you trust this app and the domain in the message matches the domain of the current web application.
@@ -55,15 +56,12 @@ export const establishSession = async (options) => {
55
56
  buildIntentInstruction(options, sessionKey, tokenInfo),
56
57
  buildStartSessionInstruction(options, sessionKey, tokenInfo),
57
58
  ]);
58
- return sendSessionEstablishTransaction(options, sessionKey, [
59
- ...buildCreateAssociatedTokenAccountInstructions(options, tokenInfo),
60
- intentInstruction,
61
- startSessionInstruction,
62
- ], options.sessionEstablishmentLookupTable);
59
+ return sendSessionEstablishTransaction(options, sessionKey, [intentInstruction, startSessionInstruction], options.sessionEstablishmentLookupTable);
63
60
  }
64
61
  };
65
62
  const sendSessionEstablishTransaction = async (options, sessionKey, instructions, sessionEstablishmentLookupTable) => {
66
63
  const result = await options.context.sendTransaction(sessionKey, instructions, {
64
+ variation: "Session Establishment",
67
65
  addressLookupTable: sessionEstablishmentLookupTable ??
68
66
  SESSION_ESTABLISHMENT_LOOKUP_TABLE_ADDRESS[options.context.network],
69
67
  });
@@ -92,9 +90,9 @@ export const revokeSession = async (options) => {
92
90
  session: options.session.sessionPublicKey,
93
91
  })
94
92
  .instruction();
95
- return options.context.sendTransaction(options.session.sessionKey, [
96
- instruction,
97
- ]);
93
+ return options.context.sendTransaction(options.session.sessionKey, [instruction], {
94
+ variation: "Session Revocation",
95
+ });
98
96
  }
99
97
  else {
100
98
  return;
@@ -117,7 +115,7 @@ const createSession = async (context, walletPublicKey, sessionKey) => {
117
115
  walletPublicKey,
118
116
  sessionKey,
119
117
  payer: context.payer,
120
- sendTransaction: (instructions) => context.sendTransaction(sessionKey, instructions),
118
+ sendTransaction: (instructions, extraConfig) => context.sendTransaction(sessionKey, instructions, extraConfig),
121
119
  sessionInfo,
122
120
  };
123
121
  };
@@ -420,7 +418,6 @@ const amountToString = (amount, decimals) => {
420
418
  ...(decimalTruncated === "" ? [] : [".", decimalTruncated]),
421
419
  ].join("");
422
420
  };
423
- const buildCreateAssociatedTokenAccountInstructions = (options, tokens) => tokens.map(({ mint }) => createAssociatedTokenAccountIdempotentInstruction(options.context.payer, getAssociatedTokenAddressSync(mint, options.walletPublicKey), options.walletPublicKey, mint));
424
421
  export const getDomainRecordAddress = (domain) => {
425
422
  const hash = sha256(domain);
426
423
  return PublicKey.findProgramAddressSync([Buffer.from("domain-record"), hash], new PublicKey(DomainRegistryIdl.address))[0];
@@ -517,7 +514,7 @@ const getFee = async (context) => {
517
514
  mint: metaplexPublicKey(usdcMintAddress),
518
515
  })[0],
519
516
  mint: usdcMint,
520
- symbolOrMint: context.network === Network.Mainnet ? "USDC.s" : "USDC",
517
+ symbolOrMint: "USDC.s",
521
518
  decimals: USDC_DECIMALS,
522
519
  fee: {
523
520
  intrachainTransfer: BigInt(feeConfig.intrachainTransferFee.toString()),
@@ -547,12 +544,16 @@ export const sendTransfer = async (options) => {
547
544
  feeSource: getAssociatedTokenAddressSync(options.feeConfig.mint, options.walletPublicKey),
548
545
  mint: options.mint,
549
546
  source: sourceAta,
550
- sponsor: options.context.payer,
547
+ sponsor: options.context.internalPayer,
548
+ metadata:
551
549
  // eslint-disable-next-line unicorn/no-null
552
- metadata: symbol === undefined ? null : new PublicKey(metadataAddress),
550
+ symbol === undefined ? null : new PublicKey(metadataAddress),
553
551
  })
554
552
  .instruction(),
555
- ]);
553
+ ], {
554
+ variation: "Intent Transfer",
555
+ paymasterDomain: SESSIONS_INTERNAL_PAYMASTER_DOMAIN,
556
+ });
556
557
  };
557
558
  const buildTransferIntentInstruction = async (program, options, symbol, feeToken, feeAmount) => {
558
559
  const [nonce, { decimals }] = await Promise.all([
@@ -582,7 +583,7 @@ const buildTransferIntentInstruction = async (program, options, symbol, feeToken
582
583
  const BRIDGE_OUT_MESSAGE_HEADER = `Fogo Bridge Transfer:
583
584
  Signing this intent will bridge out the tokens as described below.
584
585
  `;
585
- const BRIDGE_OUT_CUS = 220_000;
586
+ const BRIDGE_OUT_CUS = 240_000;
586
587
  export const bridgeOut = async (options) => {
587
588
  const { wh, route, transferRequest, transferParams, decimals } = await buildWormholeTransfer(options, options.context.connection);
588
589
  // @ts-expect-error the wormhole client types are incorrect and do not
@@ -603,10 +604,10 @@ export const bridgeOut = async (options) => {
603
604
  program.methods
604
605
  .bridgeNttTokens({
605
606
  payDestinationAtaRent: !destinationAtaExists,
606
- signedQuoteBytes: Buffer.from(quote.signedQuote),
607
+ signedQuoteBytes: [...quote.signedQuote],
607
608
  })
608
609
  .accounts({
609
- sponsor: options.context.payer,
610
+ sponsor: options.context.internalPayer,
610
611
  mint: options.fromToken.mint,
611
612
  metadata: metadata?.symbol === undefined
612
613
  ? // eslint-disable-next-line unicorn/no-null
@@ -624,6 +625,8 @@ export const bridgeOut = async (options) => {
624
625
  ComputeBudgetProgram.setComputeUnitLimit({ units: BRIDGE_OUT_CUS }),
625
626
  ...instructions,
626
627
  ], {
628
+ variation: "Intent NTT Bridge",
629
+ paymasterDomain: SESSIONS_INTERNAL_PAYMASTER_DOMAIN,
627
630
  extraSigners: [outboxItem],
628
631
  addressLookupTable: BRIDGING_ADDRESS_LOOKUP_TABLE[options.context.network]?.[options.fromToken.mint.toBase58()],
629
632
  });
@@ -707,12 +710,17 @@ export const bridgeIn = async (options) => {
707
710
  return await routes.checkAndCompleteTransfer(route, await route.initiate(transferRequest, {
708
711
  address: () => options.walletPublicKey.toBase58(),
709
712
  chain: () => "Solana",
710
- signAndSend: (transactions) => Promise.all(transactions.map(({ transaction }) => options.solanaWallet.sendTransaction(
711
- // Hooray for Wormhole's incomplete typing eh?
712
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
713
- transaction.transaction, solanaConnection,
714
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
715
- { signers: transaction.signers }))),
713
+ sign: (transactions) => Promise.all(transactions.map(async ({ transaction }) => {
714
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
715
+ const signedTx = await options.solanaWallet.signTransaction(
716
+ // Hooray for Wormhole's incomplete typing eh?
717
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
718
+ transaction.transaction);
719
+ // Hooray for Wormhole's incomplete typing eh?
720
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
721
+ signedTx.sign(transaction.signers);
722
+ return signedTx.serialize();
723
+ })),
716
724
  }, quote, Wormhole.chainAddress("Fogo", options.walletPublicKey.toBase58())));
717
725
  }
718
726
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fogo/sessions-sdk",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "description": "A set of utilities for integrating with Fogo sessions",
5
5
  "keywords": [
6
6
  "fogo",