@fogo/sessions-sdk 0.1.0 → 0.1.1

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,10 +1,7 @@
1
1
  import type { GetLatestBlockhashApi, Instruction, Rpc, Transaction, TransactionWithLifetime } from "@solana/kit";
2
2
  import type { TransactionError } from "@solana/web3.js";
3
3
  import { Keypair, PublicKey, TransactionInstruction, VersionedTransaction, Connection as Web3Connection } from "@solana/web3.js";
4
- export declare enum Network {
5
- Testnet = 0,
6
- Mainnet = 1
7
- }
4
+ import { Network } from "./network.js";
8
5
  export declare enum TransactionResultType {
9
6
  Success = 0,
10
7
  Failed = 1
@@ -37,7 +34,7 @@ export declare const createSessionConnection: (options: {
37
34
  connection: Web3Connection;
38
35
  network: Network;
39
36
  getSolanaConnection: () => Promise<Web3Connection>;
40
- sendToPaymaster: (domain: string, sessionKey: CryptoKeyPair | undefined, instructions: TransactionOrInstructions, extraConfig?: SendTransactionOptions) => Promise<TransactionResult>;
37
+ sendToPaymaster: (domain: string, sessionKey: CryptoKeyPair | undefined, instructions: TransactionOrInstructions, walletPublicKey: PublicKey, extraConfig?: SendTransactionOptions) => Promise<TransactionResult>;
41
38
  getSponsor: (domain: string) => Promise<PublicKey>;
42
39
  };
43
40
  export type TransactionOrInstructions = (TransactionInstruction | Instruction)[] | VersionedTransaction | (Transaction & TransactionWithLifetime);
package/cjs/connection.js CHANGED
@@ -1,22 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createSessionConnection = exports.TransactionResultType = exports.Network = void 0;
3
+ exports.createSessionConnection = exports.TransactionResultType = void 0;
4
+ const anchor_1 = require("@coral-xyz/anchor");
5
+ const sessions_idls_1 = require("@fogo/sessions-idls");
6
+ const sha2_1 = require("@noble/hashes/sha2");
4
7
  const compat_1 = require("@solana/compat");
5
8
  const kit_1 = require("@solana/kit");
9
+ const spl_token_1 = require("@solana/spl-token");
6
10
  const web3_js_1 = require("@solana/web3.js");
7
11
  const zod_1 = require("zod");
8
- var Network;
9
- (function (Network) {
10
- Network[Network["Testnet"] = 0] = "Testnet";
11
- Network[Network["Mainnet"] = 1] = "Mainnet";
12
- })(Network || (exports.Network = Network = {}));
12
+ const mints_js_1 = require("./mints.js");
13
+ const network_js_1 = require("./network.js");
13
14
  const DEFAULT_RPC = {
14
- [Network.Testnet]: "https://testnet.fogo.io",
15
- [Network.Mainnet]: "https://mainnet.fogo.io",
15
+ [network_js_1.Network.Testnet]: "https://testnet.fogo.io",
16
+ [network_js_1.Network.Mainnet]: "https://mainnet.fogo.io",
16
17
  };
17
18
  const DEFAULT_PAYMASTER = {
18
- [Network.Testnet]: "https://fogo-testnet.dourolabs-paymaster.xyz",
19
- [Network.Mainnet]: "https://fogo-mainnet.dourolabs-paymaster.xyz",
19
+ [network_js_1.Network.Testnet]: "https://fogo-testnet.dourolabs-paymaster.xyz",
20
+ [network_js_1.Network.Mainnet]: "https://fogo-mainnet.dourolabs-paymaster.xyz",
20
21
  };
21
22
  var TransactionResultType;
22
23
  (function (TransactionResultType) {
@@ -45,7 +46,7 @@ const createSessionConnection = (options) => {
45
46
  connection,
46
47
  network: options.network,
47
48
  getSolanaConnection: createSolanaConnectionGetter(options.network),
48
- sendToPaymaster: async (domain, sessionKey, instructions, extraConfig) => sendToPaymaster({ ...options, rpc, connection, addressLookupTableCache, sponsorCache }, domain, sessionKey, instructions, extraConfig),
49
+ sendToPaymaster: async (domain, sessionKey, instructions, walletPublicKey, extraConfig) => sendToPaymaster({ ...options, rpc, connection, addressLookupTableCache, sponsorCache }, domain, sessionKey, instructions, walletPublicKey, extraConfig),
49
50
  getSponsor: (domain) => getSponsor(options, sponsorCache, domain),
50
51
  };
51
52
  };
@@ -69,13 +70,13 @@ const createSolanaConnectionGetter = (network) => {
69
70
  };
70
71
  };
71
72
  const NETWORK_TO_QUERY_PARAM = {
72
- [Network.Mainnet]: "mainnet",
73
- [Network.Testnet]: "testnet",
73
+ [network_js_1.Network.Mainnet]: "mainnet",
74
+ [network_js_1.Network.Testnet]: "testnet",
74
75
  };
75
- const sendToPaymaster = async (connection, domain, sessionKey, instructions, extraConfig) => {
76
+ const sendToPaymaster = async (connection, domain, sessionKey, instructions, walletPublicKey, extraConfig) => {
76
77
  const signerKeys = await getSignerKeys(sessionKey, extraConfig?.extraSigners);
77
78
  const transaction = Array.isArray(instructions)
78
- ? await buildTransaction(connection, domain, signerKeys, instructions, extraConfig)
79
+ ? await buildTransaction(connection, domain, sessionKey, signerKeys, instructions, walletPublicKey, extraConfig)
79
80
  : await addSignaturesToExistingTransaction(instructions, signerKeys);
80
81
  if (connection.sendToPaymaster === undefined) {
81
82
  const url = new URL("/api/sponsor_and_send", connection.paymaster ?? DEFAULT_PAYMASTER[connection.network]);
@@ -103,8 +104,9 @@ const sendToPaymaster = async (connection, domain, sessionKey, instructions, ext
103
104
  return connection.sendToPaymaster(transaction);
104
105
  }
105
106
  };
106
- const buildTransaction = async (connection, domain, signerKeys, instructions, extraConfig) => {
107
- const [{ value: latestBlockhash }, sponsor, addressLookupTable, signers] = await Promise.all([
107
+ const buildTransaction = async (connection, domain, sessionKey, signerKeys, instructions, walletPublicKey, extraConfig) => {
108
+ const feeMint = new web3_js_1.PublicKey(mints_js_1.USDC_MINT[connection.network]); // TODO: make this configurable
109
+ const [{ value: latestBlockhash }, sponsor, addressLookupTable, signers, feeAmount, sessionKeyAddress,] = await Promise.all([
108
110
  connection.rpc.getLatestBlockhash().send(),
109
111
  connection.sponsor === undefined
110
112
  ? getSponsor(connection, connection.sponsorCache, domain)
@@ -113,15 +115,51 @@ const buildTransaction = async (connection, domain, signerKeys, instructions, ex
113
115
  ? Promise.resolve(undefined)
114
116
  : getAddressLookupTable(connection.connection, connection.addressLookupTableCache, extraConfig.addressLookupTable),
115
117
  Promise.all(signerKeys.map((signer) => (0, kit_1.createSignerFromKeyPair)(signer))),
118
+ getFee(connection, domain, extraConfig?.variation, feeMint),
119
+ sessionKey === undefined
120
+ ? Promise.resolve(undefined)
121
+ : (0, kit_1.getAddressFromPublicKey)(sessionKey.publicKey),
116
122
  ]);
123
+ const tollboothInstruction = await buildTollboothInstructionIfNeeded({
124
+ sessionKeyAddress,
125
+ walletPublicKey,
126
+ domain,
127
+ feeMint,
128
+ feeAmount,
129
+ });
117
130
  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
131
  ? (0, compat_1.fromLegacyTransactionInstruction)(instruction)
119
- : instruction), tx), (tx) => addressLookupTable === undefined
132
+ : instruction), tx), (tx) => tollboothInstruction === undefined
133
+ ? tx
134
+ : (0, kit_1.appendTransactionMessageInstructions)([tollboothInstruction], tx), (tx) => addressLookupTable === undefined
120
135
  ? tx
121
136
  : (0, kit_1.compressTransactionMessageUsingAddressLookupTables)(tx, {
122
137
  [(0, compat_1.fromLegacyPublicKey)(addressLookupTable.key)]: addressLookupTable.state.addresses.map((address) => (0, compat_1.fromLegacyPublicKey)(address)),
123
138
  }), (tx) => (0, kit_1.addSignersToTransactionMessage)(signers, tx)));
124
139
  };
140
+ const getDomainTollRecipientAddress = (domain) => {
141
+ const hash = (0, sha2_1.sha256)(domain);
142
+ return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("toll_recipient"), Buffer.from([0]), hash], new web3_js_1.PublicKey(sessions_idls_1.TollboothIdl.address))[0];
143
+ };
144
+ const buildTollboothInstructionIfNeeded = async ({ sessionKeyAddress, walletPublicKey, domain, feeMint, feeAmount, }) => {
145
+ if (feeAmount.gt(new anchor_1.BN(0)) && sessionKeyAddress !== undefined) {
146
+ const userTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(feeMint, walletPublicKey);
147
+ const recipient = getDomainTollRecipientAddress(domain);
148
+ const instruction = await new sessions_idls_1.TollboothProgram(new anchor_1.AnchorProvider({}, {})).methods
149
+ .payToll(feeAmount, 0)
150
+ .accounts({
151
+ session: new web3_js_1.PublicKey(sessionKeyAddress),
152
+ source: userTokenAccount,
153
+ destination: (0, spl_token_1.getAssociatedTokenAddressSync)(feeMint, recipient, true),
154
+ mint: feeMint,
155
+ })
156
+ .instruction();
157
+ return (0, compat_1.fromLegacyTransactionInstruction)(instruction);
158
+ }
159
+ else {
160
+ return undefined;
161
+ }
162
+ };
125
163
  const addSignaturesToExistingTransaction = (transaction, signerKeys) => (0, kit_1.partiallySignTransaction)(signerKeys, transaction instanceof web3_js_1.VersionedTransaction
126
164
  ? (0, compat_1.fromVersionedTransaction)(transaction) // VersionedTransaction has a lifetime so it's fine to cast it so we can call partiallySignTransaction
127
165
  : transaction);
@@ -173,6 +211,24 @@ const getSponsor = async (options, sponsorCache, domain) => {
173
211
  return value;
174
212
  }
175
213
  };
214
+ const getFee = async (options, domain, variation, mint) => {
215
+ if (variation) {
216
+ const url = new URL("/api/fee", options.paymaster ?? DEFAULT_PAYMASTER[options.network]);
217
+ url.searchParams.set("domain", domain);
218
+ url.searchParams.set("variation", variation);
219
+ url.searchParams.set("mint", mint.toBase58());
220
+ const response = await fetch(url);
221
+ if (response.status === 200) {
222
+ return new anchor_1.BN(await response.text());
223
+ }
224
+ else {
225
+ throw new PaymasterResponseError(response.status, await response.text());
226
+ }
227
+ }
228
+ else {
229
+ return new anchor_1.BN(0);
230
+ }
231
+ };
176
232
  const getAddressLookupTable = async (connection, addressLookupTableCache, addressLookupTableAddress) => {
177
233
  const value = addressLookupTableCache.get(addressLookupTableAddress);
178
234
  if (value === undefined) {
package/cjs/context.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Connection as Web3Connection } from "@solana/web3.js";
1
+ import { type PublicKey, Connection as Web3Connection } from "@solana/web3.js";
2
2
  import type { Connection, SendTransactionOptions as SendTransactionBaseOptions, TransactionOrInstructions } from "./connection.js";
3
3
  export declare const SESSIONS_INTERNAL_PAYMASTER_DOMAIN = "sessions";
4
4
  export declare const createSessionContext: (options: {
@@ -8,13 +8,13 @@ export declare const createSessionContext: (options: {
8
8
  }) => Promise<{
9
9
  chainId: string;
10
10
  domain: string;
11
- payer: import("@solana/web3.js").PublicKey;
12
- internalPayer: import("@solana/web3.js").PublicKey;
11
+ payer: PublicKey;
12
+ internalPayer: PublicKey;
13
13
  getSolanaConnection: () => Promise<Web3Connection>;
14
14
  connection: Web3Connection;
15
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>;
16
- network: import("./connection.js").Network;
17
- sendTransaction: (sessionKey: CryptoKeyPair | undefined, instructions: TransactionOrInstructions, sendTxOptions?: SendTransactionOptions) => Promise<import("./connection.js").TransactionResult>;
16
+ network: import("./network.js").Network;
17
+ sendTransaction: (sessionKey: CryptoKeyPair | undefined, instructions: TransactionOrInstructions, walletPublicKey: PublicKey, sendTxOptions?: SendTransactionOptions) => Promise<import("./connection.js").TransactionResult>;
18
18
  }>;
19
19
  export type SendTransactionOptions = SendTransactionBaseOptions & {
20
20
  paymasterDomain?: string | undefined;
package/cjs/context.js CHANGED
@@ -22,7 +22,7 @@ const createSessionContext = async (options) => {
22
22
  connection: options.connection.connection,
23
23
  rpc: options.connection.rpc,
24
24
  network: options.connection.network,
25
- sendTransaction: (sessionKey, instructions, sendTxOptions) => options.connection.sendToPaymaster(sendTxOptions?.paymasterDomain ?? domain, sessionKey, instructions, {
25
+ sendTransaction: (sessionKey, instructions, walletPublicKey, sendTxOptions) => options.connection.sendToPaymaster(sendTxOptions?.paymasterDomain ?? domain, sessionKey, instructions, walletPublicKey, {
26
26
  ...sendTxOptions,
27
27
  addressLookupTable: sendTxOptions?.addressLookupTable ??
28
28
  options.defaultAddressLookupTableAddress,