@fogo/sessions-sdk 0.0.16 → 0.0.18

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.
@@ -0,0 +1,57 @@
1
+ import type { Transaction, Instruction, TransactionWithLifetime } from "@solana/kit";
2
+ import type { AddressLookupTableAccount, TransactionError } from "@solana/web3.js";
3
+ import { Connection as Web3Connection, TransactionInstruction, VersionedTransaction, PublicKey } from "@solana/web3.js";
4
+ export declare enum Network {
5
+ Testnet = 0,
6
+ Mainnet = 1
7
+ }
8
+ export declare const DEFAULT_RPC: {
9
+ 0: string;
10
+ 1: string;
11
+ };
12
+ export declare const DEFAULT_PAYMASTER: {
13
+ 0: string;
14
+ 1: string;
15
+ };
16
+ export declare enum TransactionResultType {
17
+ Success = 0,
18
+ Failed = 1
19
+ }
20
+ declare const TransactionResult: {
21
+ Success: (signature: string) => {
22
+ type: TransactionResultType.Success;
23
+ signature: string;
24
+ };
25
+ Failed: (signature: string, error: TransactionError) => {
26
+ type: TransactionResultType.Failed;
27
+ signature: string;
28
+ error: TransactionError;
29
+ };
30
+ };
31
+ export type TransactionResult = ReturnType<(typeof TransactionResult)[keyof typeof TransactionResult]>;
32
+ export declare const createSessionConnection: (options: {
33
+ network: Network;
34
+ rpc?: string | URL | undefined;
35
+ paymaster?: undefined;
36
+ sendToPaymaster?: undefined;
37
+ sponsor?: undefined;
38
+ } | ({
39
+ network?: Network | undefined;
40
+ rpc: string | URL;
41
+ } & ({
42
+ paymaster: string | URL;
43
+ sendToPaymaster?: undefined;
44
+ sponsor?: undefined;
45
+ } | {
46
+ paymaster?: undefined;
47
+ sendToPaymaster: (transaction: Transaction) => Promise<TransactionResult>;
48
+ sponsor: PublicKey;
49
+ }))) => {
50
+ 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>;
51
+ connection: Web3Connection;
52
+ sendToPaymaster: (domain: string, sponsor: PublicKey, addressLookupTables: AddressLookupTableAccount[] | undefined, sessionKey: CryptoKeyPair | undefined, instructions: (TransactionInstruction | Instruction)[] | VersionedTransaction | (Transaction & TransactionWithLifetime)) => Promise<TransactionResult>;
53
+ getSponsor: (domain: string) => Promise<PublicKey>;
54
+ getAddressLookupTables: (addressLookupTableAddress?: string) => Promise<AddressLookupTableAccount[] | undefined>;
55
+ };
56
+ export type Connection = ReturnType<typeof createSessionConnection>;
57
+ export {};
@@ -1,13 +1,24 @@
1
- import { AnchorProvider } from "@coral-xyz/anchor";
2
- import { ChainIdProgram } from "@fogo/sessions-idls";
3
1
  import { fromLegacyPublicKey, fromLegacyTransactionInstruction, fromVersionedTransaction, } from "@solana/compat";
4
- import { createTransactionMessage, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstructions, getBase64EncodedWireTransaction, partiallySignTransactionMessageWithSigners, pipe, createSolanaRpc, addSignersToTransactionMessage, compressTransactionMessageUsingAddressLookupTables, createSignerFromKeyPair, partiallySignTransaction, } from "@solana/kit";
5
- import { PublicKey, Keypair, TransactionInstruction, VersionedTransaction, } from "@solana/web3.js";
2
+ import { createSolanaRpc, getBase64EncodedWireTransaction, createTransactionMessage, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstructions, partiallySignTransactionMessageWithSigners, pipe, addSignersToTransactionMessage, compressTransactionMessageUsingAddressLookupTables, createSignerFromKeyPair, partiallySignTransaction, } from "@solana/kit";
3
+ import { Connection as Web3Connection, TransactionInstruction, VersionedTransaction, PublicKey, } from "@solana/web3.js";
6
4
  import { z } from "zod";
7
- // eslint-disable-next-line unicorn/no-typeof-undefined
8
- const IS_BROWSER = typeof globalThis.window !== "undefined";
9
- const DEFAULT_PAYMASTER = "https://paymaster.fogo.io";
10
- const DEFAULT_ADDRESS_LOOKUP_TABLE_ADDRESS = "B8cUjJMqaWWTNNSTXBmeptjWswwCH1gTSCRYv4nu7kJW";
5
+ export var Network;
6
+ (function (Network) {
7
+ Network[Network["Testnet"] = 0] = "Testnet";
8
+ Network[Network["Mainnet"] = 1] = "Mainnet";
9
+ })(Network || (Network = {}));
10
+ export const DEFAULT_RPC = {
11
+ [Network.Testnet]: "https://testnet.fogo.io",
12
+ [Network.Mainnet]: "https://mainnet.fogo.io",
13
+ };
14
+ export const DEFAULT_PAYMASTER = {
15
+ [Network.Testnet]: "https://paymaster.fogo.io",
16
+ [Network.Mainnet]: "https://paymaster.dourolabs.app",
17
+ };
18
+ const DEFAULT_ADDRESS_LOOKUP_TABLE_ADDRESS = {
19
+ [Network.Testnet]: "B8cUjJMqaWWTNNSTXBmeptjWswwCH1gTSCRYv4nu7kJW",
20
+ [Network.Mainnet]: undefined,
21
+ };
11
22
  export var TransactionResultType;
12
23
  (function (TransactionResultType) {
13
24
  TransactionResultType[TransactionResultType["Success"] = 0] = "Success";
@@ -24,22 +35,51 @@ const TransactionResult = {
24
35
  error,
25
36
  }),
26
37
  };
27
- export const createSolanaWalletAdapter = async (options) => {
28
- const addressLookupTables = await getAddressLookupTables(options.connection, options.addressLookupTableAddress);
29
- const domain = getDomain(options.domain);
30
- const sponsor = await getSponsor(options, domain);
38
+ export const createSessionConnection = (options) => {
39
+ // For some reason, typescript is unable to narrow this type even though it's
40
+ // obvious that `rpc` can only be `undefined` if `network` is defined. I
41
+ // don't like the non-null assertion, but here we can guarantee it's safe (and
42
+ // typescript really should be able to narrow this...)
43
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
44
+ const rpcUrl = (options.rpc ?? DEFAULT_RPC[options.network]).toString();
45
+ const rpc = createSolanaRpc(rpcUrl);
46
+ const connection = new Web3Connection(rpcUrl, "confirmed");
31
47
  return {
32
- connection: options.connection,
33
- payer: sponsor,
34
- chainId: await fetchChainId(options.connection),
35
- domain: getDomain(options.domain),
36
- sendTransaction: async (sessionKey, instructions) => {
37
- const rpc = createSolanaRpc(options.connection.rpcEndpoint);
48
+ rpc,
49
+ connection,
50
+ sendToPaymaster: async (domain, sponsor, addressLookupTables, sessionKey, instructions) => {
38
51
  const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
39
- return await sendToPaymaster(options, await buildTransaction(latestBlockhash, sessionKey, sponsor, instructions, addressLookupTables), domain);
52
+ const transaction = await buildTransaction(latestBlockhash, sessionKey, sponsor, instructions, addressLookupTables);
53
+ return sendToPaymaster(options, domain, transaction);
40
54
  },
55
+ getSponsor: (domain) => getSponsor(options, domain),
56
+ getAddressLookupTables: (addressLookupTableAddress) => getAddressLookupTables(options, connection, addressLookupTableAddress),
41
57
  };
42
58
  };
59
+ const sendToPaymaster = async (options, domain, transaction) => {
60
+ if (options.sendToPaymaster === undefined) {
61
+ const url = new URL("/api/sponsor_and_send", options.paymaster ?? DEFAULT_PAYMASTER[options.network]);
62
+ url.searchParams.set("domain", domain);
63
+ const response = await fetch(url, {
64
+ method: "POST",
65
+ headers: {
66
+ "Content-Type": "application/json",
67
+ },
68
+ body: JSON.stringify({
69
+ transaction: getBase64EncodedWireTransaction(transaction),
70
+ }),
71
+ });
72
+ if (response.status === 200) {
73
+ return sponsorAndSendResponseSchema.parse(await response.json());
74
+ }
75
+ else {
76
+ throw new PaymasterResponseError(response.status, await response.text());
77
+ }
78
+ }
79
+ else {
80
+ return options.sendToPaymaster(transaction);
81
+ }
82
+ };
43
83
  const buildTransaction = async (latestBlockhash, sessionKey, sponsor, instructions, addressLookupTables) => {
44
84
  const sessionKeySigner = sessionKey
45
85
  ? await createSignerFromKeyPair(sessionKey)
@@ -63,22 +103,6 @@ const buildTransaction = async (latestBlockhash, sessionKey, sponsor, instructio
63
103
  : partiallySignTransaction([sessionKey], tx);
64
104
  }
65
105
  };
66
- const getSponsor = async (options, domain) => {
67
- if ("sponsor" in options) {
68
- return options.sponsor;
69
- }
70
- else {
71
- const url = new URL("/api/sponsor_pubkey", options.paymaster ?? DEFAULT_PAYMASTER);
72
- url.searchParams.set("domain", domain);
73
- const response = await fetch(url);
74
- if (response.status === 200) {
75
- return new PublicKey(z.string().parse(await response.text()));
76
- }
77
- else {
78
- throw new PaymasterResponseError(response.status, await response.text());
79
- }
80
- }
81
- };
82
106
  const sponsorAndSendResponseSchema = z
83
107
  .discriminatedUnion("type", [
84
108
  z.object({
@@ -98,59 +122,35 @@ const sponsorAndSendResponseSchema = z
98
122
  ? TransactionResult.Success(data.signature)
99
123
  : TransactionResult.Failed(data.signature, data.error);
100
124
  });
101
- const sendToPaymaster = async (options, transaction, domain) => {
102
- if ("sendToPaymaster" in options) {
103
- return options.sendToPaymaster(transaction);
104
- }
105
- else {
106
- const url = new URL("/api/sponsor_and_send", options.paymaster ?? DEFAULT_PAYMASTER);
125
+ const getSponsor = async (options, domain) => {
126
+ if (options.sponsor === undefined) {
127
+ const url = new URL("/api/sponsor_pubkey", options.paymaster ?? DEFAULT_PAYMASTER[options.network]);
107
128
  url.searchParams.set("domain", domain);
108
- const response = await fetch(url, {
109
- method: "POST",
110
- headers: {
111
- "Content-Type": "application/json",
112
- },
113
- body: JSON.stringify({
114
- transaction: getBase64EncodedWireTransaction(transaction),
115
- }),
116
- });
129
+ const response = await fetch(url);
117
130
  if (response.status === 200) {
118
- return sponsorAndSendResponseSchema.parse(await response.json());
131
+ return new PublicKey(z.string().parse(await response.text()));
119
132
  }
120
133
  else {
121
134
  throw new PaymasterResponseError(response.status, await response.text());
122
135
  }
123
136
  }
124
- };
125
- const getAddressLookupTables = async (connection, addressLookupTableAddress = DEFAULT_ADDRESS_LOOKUP_TABLE_ADDRESS) => {
126
- const addressLookupTableResult = await connection.getAddressLookupTable(new PublicKey(addressLookupTableAddress));
127
- return addressLookupTableResult.value
128
- ? [addressLookupTableResult.value]
129
- : undefined;
130
- };
131
- const fetchChainId = async (connection) => {
132
- const chainIdProgram = new ChainIdProgram(new AnchorProvider(connection, { publicKey: new Keypair().publicKey }, {})); // We mock the wallet because we don't need to sign anything
133
- const { chainIdAccount: chainIdAddress } = await chainIdProgram.methods
134
- .set("")
135
- .pubkeys(); // We use Anchor to derive the chain ID address, not caring about the actual argument of `set`
136
- if (chainIdAddress === undefined) {
137
- throw new NoChainIdAddressError();
137
+ else {
138
+ return options.sponsor;
138
139
  }
139
- const chainId = await chainIdProgram.account.chainId.fetch(chainIdAddress);
140
- return chainId.chainId;
141
140
  };
142
- const getDomain = (requestedDomain) => {
143
- const detectedDomain = IS_BROWSER ? globalThis.location.origin : undefined;
144
- if (requestedDomain === undefined) {
145
- if (detectedDomain === undefined) {
146
- throw new DomainRequiredError();
147
- }
148
- else {
149
- return detectedDomain;
150
- }
141
+ const getAddressLookupTables = async (options, connection, addressLookupTableAddress) => {
142
+ const altAddress = addressLookupTableAddress ??
143
+ (options.network === undefined
144
+ ? undefined
145
+ : DEFAULT_ADDRESS_LOOKUP_TABLE_ADDRESS[options.network]);
146
+ if (altAddress) {
147
+ const addressLookupTableResult = await connection.getAddressLookupTable(new PublicKey(altAddress));
148
+ return addressLookupTableResult.value
149
+ ? [addressLookupTableResult.value]
150
+ : undefined;
151
151
  }
152
152
  else {
153
- return requestedDomain;
153
+ return;
154
154
  }
155
155
  };
156
156
  class PaymasterResponseError extends Error {
@@ -159,15 +159,3 @@ class PaymasterResponseError extends Error {
159
159
  this.name = "PaymasterResponseError";
160
160
  }
161
161
  }
162
- class NoChainIdAddressError extends Error {
163
- constructor() {
164
- super("Failed to derive chain ID address");
165
- this.name = "NoChainIdAddressError";
166
- }
167
- }
168
- class DomainRequiredError extends Error {
169
- constructor() {
170
- super("On platforms where the origin cannot be determined, you must pass a domain to create a session.");
171
- this.name = "DomainRequiredError";
172
- }
173
- }
@@ -0,0 +1,15 @@
1
+ import { Connection as Web3Connection } from "@solana/web3.js";
2
+ import type { Connection } from "./connection.js";
3
+ export declare const createSessionContext: (options: {
4
+ connection: Connection;
5
+ addressLookupTableAddress?: string | undefined;
6
+ domain?: string | undefined;
7
+ }) => Promise<{
8
+ chainId: string;
9
+ domain: string;
10
+ payer: import("@solana/web3.js").PublicKey;
11
+ connection: Web3Connection;
12
+ 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>;
13
+ sendTransaction: (sessionKey: CryptoKeyPair | undefined, instructions: Parameters<typeof options.connection.sendToPaymaster>[4]) => Promise<import("./connection.js").TransactionResult>;
14
+ }>;
15
+ export type SessionContext = Awaited<ReturnType<typeof createSessionContext>>;
package/esm/context.js ADDED
@@ -0,0 +1,55 @@
1
+ import { AnchorProvider } from "@coral-xyz/anchor";
2
+ import { ChainIdProgram } from "@fogo/sessions-idls";
3
+ import { Connection as Web3Connection, Keypair } from "@solana/web3.js";
4
+ // eslint-disable-next-line unicorn/no-typeof-undefined
5
+ const IS_BROWSER = typeof globalThis.window !== "undefined";
6
+ export const createSessionContext = async (options) => {
7
+ const addressLookupTables = await options.connection.getAddressLookupTables(options.addressLookupTableAddress);
8
+ const domain = getDomain(options.domain);
9
+ const sponsor = await options.connection.getSponsor(domain);
10
+ return {
11
+ chainId: await fetchChainId(options.connection.connection),
12
+ domain: getDomain(options.domain),
13
+ payer: sponsor,
14
+ connection: options.connection.connection,
15
+ rpc: options.connection.rpc,
16
+ sendTransaction: (sessionKey, instructions) => options.connection.sendToPaymaster(domain, sponsor, addressLookupTables, sessionKey, instructions),
17
+ };
18
+ };
19
+ const fetchChainId = async (connection) => {
20
+ const chainIdProgram = new ChainIdProgram(new AnchorProvider(connection, { publicKey: new Keypair().publicKey }, {})); // We mock the wallet because we don't need to sign anything
21
+ const { chainIdAccount: chainIdAddress } = await chainIdProgram.methods
22
+ .set("")
23
+ .pubkeys(); // We use Anchor to derive the chain ID address, not caring about the actual argument of `set`
24
+ if (chainIdAddress === undefined) {
25
+ throw new NoChainIdAddressError();
26
+ }
27
+ const chainId = await chainIdProgram.account.chainId.fetch(chainIdAddress);
28
+ return chainId.chainId;
29
+ };
30
+ const getDomain = (requestedDomain) => {
31
+ const detectedDomain = IS_BROWSER ? globalThis.location.origin : undefined;
32
+ if (requestedDomain === undefined) {
33
+ if (detectedDomain === undefined) {
34
+ throw new DomainRequiredError();
35
+ }
36
+ else {
37
+ return detectedDomain;
38
+ }
39
+ }
40
+ else {
41
+ return requestedDomain;
42
+ }
43
+ };
44
+ class NoChainIdAddressError extends Error {
45
+ constructor() {
46
+ super("Failed to derive chain ID address");
47
+ this.name = "NoChainIdAddressError";
48
+ }
49
+ }
50
+ class DomainRequiredError extends Error {
51
+ constructor() {
52
+ super("On platforms where the origin cannot be determined, you must pass a domain to create a session.");
53
+ this.name = "DomainRequiredError";
54
+ }
55
+ }
package/esm/index.d.ts CHANGED
@@ -2,10 +2,12 @@ import type { Connection, TransactionError } from "@solana/web3.js";
2
2
  import { PublicKey } from "@solana/web3.js";
3
3
  import BN from "bn.js";
4
4
  import { z } from "zod";
5
- import type { SessionAdapter, TransactionResult } from "./adapter.js";
6
- export { createSolanaWalletAdapter, TransactionResultType, type SessionAdapter, type TransactionResult, } from "./adapter.js";
5
+ import type { TransactionResult } from "./connection.js";
6
+ import type { SessionContext } from "./context.js";
7
+ export { type SessionContext, createSessionContext } from "./context.js";
8
+ export { type TransactionResult, type Connection, Network, TransactionResultType, createSessionConnection, } from "./connection.js";
7
9
  type EstablishSessionOptions = {
8
- adapter: SessionAdapter;
10
+ context: SessionContext;
9
11
  walletPublicKey: PublicKey;
10
12
  signMessage: (message: Uint8Array) => Promise<Uint8Array>;
11
13
  expires: Date;
@@ -19,7 +21,7 @@ type EstablishSessionOptions = {
19
21
  });
20
22
  export declare const establishSession: (options: EstablishSessionOptions) => Promise<EstablishSessionResult>;
21
23
  export declare const replaceSession: (options: {
22
- adapter: SessionAdapter;
24
+ context: SessionContext;
23
25
  session: Session;
24
26
  signMessage: (message: Uint8Array) => Promise<Uint8Array>;
25
27
  expires: Date;
@@ -31,10 +33,10 @@ export declare const replaceSession: (options: {
31
33
  unlimited: true;
32
34
  })) => Promise<EstablishSessionResult>;
33
35
  export declare const revokeSession: (options: {
34
- adapter: SessionAdapter;
36
+ context: SessionContext;
35
37
  session: Session;
36
38
  }) => Promise<TransactionResult | undefined>;
37
- export declare const reestablishSession: (adapter: SessionAdapter, walletPublicKey: PublicKey, sessionKey: CryptoKeyPair) => Promise<Session | undefined>;
39
+ export declare const reestablishSession: (context: SessionContext, walletPublicKey: PublicKey, sessionKey: CryptoKeyPair) => Promise<Session | undefined>;
38
40
  export declare const getSessionAccount: (connection: Connection, sessionPublicKey: PublicKey) => Promise<{
39
41
  authorizedPrograms: {
40
42
  type: AuthorizedProgramsType.All;
@@ -1302,11 +1304,11 @@ export type Session = {
1302
1304
  sessionKey: CryptoKeyPair;
1303
1305
  walletPublicKey: PublicKey;
1304
1306
  payer: PublicKey;
1305
- sendTransaction: (instructions: Parameters<SessionAdapter["sendTransaction"]>[1]) => Promise<TransactionResult>;
1307
+ sendTransaction: (instructions: Parameters<SessionContext["sendTransaction"]>[1]) => Promise<TransactionResult>;
1306
1308
  sessionInfo: NonNullable<z.infer<typeof sessionInfoSchema>>;
1307
1309
  };
1308
1310
  type SendTransferOptions = {
1309
- adapter: SessionAdapter;
1311
+ context: SessionContext;
1310
1312
  walletPublicKey: PublicKey;
1311
1313
  signMessage: (message: Uint8Array) => Promise<Uint8Array>;
1312
1314
  mint: PublicKey;
package/esm/index.js CHANGED
@@ -11,9 +11,10 @@ import { Ed25519Program, PublicKey } from "@solana/web3.js";
11
11
  import BN from "bn.js";
12
12
  import bs58 from "bs58";
13
13
  import { z } from "zod";
14
- import { TransactionResultType } from "./adapter.js";
14
+ import { TransactionResultType } from "./connection.js";
15
15
  import { importKey, signMessageWithKey, verifyMessageWithKey, } from "./crypto.js";
16
- export { createSolanaWalletAdapter, TransactionResultType, } from "./adapter.js";
16
+ export { createSessionContext } from "./context.js";
17
+ export { Network, TransactionResultType, createSessionConnection, } from "./connection.js";
17
18
  const MESSAGE_HEADER = `Fogo Sessions:
18
19
  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.
19
20
  `;
@@ -36,7 +37,7 @@ export const establishSession = async (options) => {
36
37
  else {
37
38
  const filteredLimits = new Map(options.limits?.entries().filter(([, amount]) => amount > 0n));
38
39
  const tokenInfo = filteredLimits.size > 0
39
- ? await getTokenInfo(options.adapter, filteredLimits)
40
+ ? await getTokenInfo(options.context, filteredLimits)
40
41
  : [];
41
42
  const [intentInstruction, startSessionInstruction] = await Promise.all([
42
43
  buildIntentInstruction(options, sessionKey, tokenInfo),
@@ -50,10 +51,10 @@ export const establishSession = async (options) => {
50
51
  }
51
52
  };
52
53
  const sendSessionEstablishTransaction = async (options, sessionKey, instructions) => {
53
- const result = await options.adapter.sendTransaction(sessionKey, instructions);
54
+ const result = await options.context.sendTransaction(sessionKey, instructions);
54
55
  switch (result.type) {
55
56
  case TransactionResultType.Success: {
56
- const session = await createSession(options.adapter, options.walletPublicKey, sessionKey);
57
+ const session = await createSession(options.context, options.walletPublicKey, sessionKey);
57
58
  return session
58
59
  ? EstablishSessionResult.Success(result.signature, session)
59
60
  : EstablishSessionResult.Failed(result.signature, new Error("Transaction succeeded, but the session was not created"));
@@ -69,14 +70,14 @@ export const replaceSession = async (options) => establishSession({
69
70
  });
70
71
  export const revokeSession = async (options) => {
71
72
  if (options.session.sessionInfo.minor >= 2) {
72
- const instruction = await new SessionManagerProgram(new AnchorProvider(options.adapter.connection, {}, {})).methods
73
+ const instruction = await new SessionManagerProgram(new AnchorProvider(options.context.connection, {}, {})).methods
73
74
  .revokeSession()
74
75
  .accounts({
75
76
  sponsor: options.session.sessionInfo.sponsor,
76
77
  session: options.session.sessionPublicKey,
77
78
  })
78
79
  .instruction();
79
- return options.adapter.sendTransaction(options.session.sessionKey, [
80
+ return options.context.sendTransaction(options.session.sessionKey, [
80
81
  instruction,
81
82
  ]);
82
83
  }
@@ -84,24 +85,24 @@ export const revokeSession = async (options) => {
84
85
  return;
85
86
  }
86
87
  };
87
- export const reestablishSession = async (adapter, walletPublicKey, sessionKey) => createSession(adapter, walletPublicKey, sessionKey);
88
+ export const reestablishSession = async (context, walletPublicKey, sessionKey) => createSession(context, walletPublicKey, sessionKey);
88
89
  export const getSessionAccount = async (connection, sessionPublicKey) => {
89
90
  const result = await connection.getAccountInfo(sessionPublicKey, "confirmed");
90
91
  return result === null
91
92
  ? undefined
92
93
  : sessionInfoSchema.parse(new BorshAccountsCoder(SessionManagerIdl).decode("Session", result.data));
93
94
  };
94
- const createSession = async (adapter, walletPublicKey, sessionKey) => {
95
+ const createSession = async (context, walletPublicKey, sessionKey) => {
95
96
  const sessionPublicKey = new PublicKey(await getAddressFromPublicKey(sessionKey.publicKey));
96
- const sessionInfo = await getSessionAccount(adapter.connection, sessionPublicKey);
97
+ const sessionInfo = await getSessionAccount(context.connection, sessionPublicKey);
97
98
  return sessionInfo === undefined
98
99
  ? undefined
99
100
  : {
100
101
  sessionPublicKey,
101
102
  walletPublicKey,
102
103
  sessionKey,
103
- payer: adapter.payer,
104
- sendTransaction: (instructions) => adapter.sendTransaction(sessionKey, instructions),
104
+ payer: context.payer,
105
+ sendTransaction: (instructions) => context.sendTransaction(sessionKey, instructions),
105
106
  sessionInfo,
106
107
  };
107
108
  };
@@ -286,13 +287,13 @@ const SymbolOrMint = {
286
287
  mint,
287
288
  }),
288
289
  };
289
- const getTokenInfo = async (adapter, limits) => {
290
- const umi = createUmi(adapter.connection.rpcEndpoint);
290
+ const getTokenInfo = async (context, limits) => {
291
+ const umi = createUmi(context.connection.rpcEndpoint);
291
292
  return Promise.all(limits.entries().map(async ([mint, amount]) => {
292
293
  const metaplexMint = metaplexPublicKey(mint.toBase58());
293
294
  const metadataAddress = findMetadataPda(umi, { mint: metaplexMint })[0];
294
295
  const [mintInfo, metadata] = await Promise.all([
295
- getMint(adapter.connection, mint),
296
+ getMint(context.connection, mint),
296
297
  safeFetchMetadata(umi, metadataAddress),
297
298
  ]);
298
299
  return {
@@ -338,8 +339,8 @@ const addOffchainMessagePrefixToMessageIfNeeded = async (walletPublicKey, signat
338
339
  };
339
340
  const buildIntentInstruction = async (options, sessionKey, tokens) => {
340
341
  const message = await buildMessage({
341
- chainId: options.adapter.chainId,
342
- domain: options.adapter.domain,
342
+ chainId: options.context.chainId,
343
+ domain: options.context.domain,
343
344
  sessionKey,
344
345
  expires: options.expires,
345
346
  tokens,
@@ -404,18 +405,18 @@ const amountToString = (amount, decimals) => {
404
405
  ...(decimalTruncated === "" ? [] : [".", decimalTruncated]),
405
406
  ].join("");
406
407
  };
407
- const buildCreateAssociatedTokenAccountInstructions = (options, tokens) => tokens.map(({ mint }) => createAssociatedTokenAccountIdempotentInstruction(options.adapter.payer, getAssociatedTokenAddressSync(mint, options.walletPublicKey), options.walletPublicKey, mint));
408
+ const buildCreateAssociatedTokenAccountInstructions = (options, tokens) => tokens.map(({ mint }) => createAssociatedTokenAccountIdempotentInstruction(options.context.payer, getAssociatedTokenAddressSync(mint, options.walletPublicKey), options.walletPublicKey, mint));
408
409
  export const getDomainRecordAddress = (domain) => {
409
410
  const hash = sha256(domain);
410
411
  return PublicKey.findProgramAddressSync([Buffer.from("domain-record"), hash], new PublicKey(DomainRegistryIdl.address))[0];
411
412
  };
412
413
  const buildStartSessionInstruction = async (options, sessionKey, tokens) => {
413
- const instruction = new SessionManagerProgram(new AnchorProvider(options.adapter.connection, {}, {})).methods
414
+ const instruction = new SessionManagerProgram(new AnchorProvider(options.context.connection, {}, {})).methods
414
415
  .startSession()
415
416
  .accounts({
416
- sponsor: options.adapter.payer,
417
+ sponsor: options.context.payer,
417
418
  session: await getAddressFromPublicKey(sessionKey.publicKey),
418
- domainRegistry: getDomainRecordAddress(options.adapter.domain),
419
+ domainRegistry: getDomainRecordAddress(options.context.domain),
419
420
  });
420
421
  return tokens === undefined
421
422
  ? instruction.instruction()
@@ -466,14 +467,14 @@ Signing this intent will transfer the tokens as described below.
466
467
  export const sendTransfer = async (options) => {
467
468
  const sourceAta = getAssociatedTokenAddressSync(options.mint, options.walletPublicKey);
468
469
  const destinationAta = getAssociatedTokenAddressSync(options.mint, options.recipient);
469
- const program = new IntentTransferProgram(new AnchorProvider(options.adapter.connection, {}, {}));
470
- const umi = createUmi(options.adapter.connection.rpcEndpoint);
470
+ const program = new IntentTransferProgram(new AnchorProvider(options.context.connection, {}, {}));
471
+ const umi = createUmi(options.context.connection.rpcEndpoint);
471
472
  const metaplexMint = metaplexPublicKey(options.mint.toBase58());
472
473
  const metadataAddress = findMetadataPda(umi, { mint: metaplexMint })[0];
473
474
  const metadata = await safeFetchMetadata(umi, metadataAddress);
474
475
  const symbol = metadata?.symbol ?? undefined;
475
- return options.adapter.sendTransaction(undefined, [
476
- createAssociatedTokenAccountIdempotentInstruction(options.adapter.payer, destinationAta, options.recipient, options.mint),
476
+ return options.context.sendTransaction(undefined, [
477
+ createAssociatedTokenAccountIdempotentInstruction(options.context.payer, destinationAta, options.recipient, options.mint),
477
478
  await buildTransferIntentInstruction(program, options, symbol),
478
479
  await program.methods
479
480
  .sendTokens()
@@ -481,7 +482,7 @@ export const sendTransfer = async (options) => {
481
482
  destination: destinationAta,
482
483
  mint: options.mint,
483
484
  source: sourceAta,
484
- sponsor: options.adapter.payer,
485
+ sponsor: options.context.payer,
485
486
  // eslint-disable-next-line unicorn/no-null
486
487
  metadata: symbol === undefined ? null : new PublicKey(metadataAddress),
487
488
  })
@@ -491,13 +492,13 @@ export const sendTransfer = async (options) => {
491
492
  const buildTransferIntentInstruction = async (program, options, symbol) => {
492
493
  const [nonce, { decimals }] = await Promise.all([
493
494
  getNonce(program, options.walletPublicKey),
494
- getMint(options.adapter.connection, options.mint),
495
+ getMint(options.context.connection, options.mint),
495
496
  ]);
496
497
  const message = new TextEncoder().encode([
497
498
  TRANSFER_MESSAGE_HEADER,
498
499
  serializeKV({
499
500
  version: `${CURRENT_INTENT_TRANSFER_MAJOR}.${CURRENT_INTENT_TRANSFER_MINOR}`,
500
- chain_id: options.adapter.chainId,
501
+ chain_id: options.context.chainId,
501
502
  token: symbol ?? options.mint.toBase58(),
502
503
  amount: amountToString(options.amount, decimals),
503
504
  recipient: options.recipient.toBase58(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fogo/sessions-sdk",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "A set of utilities for integrating with Fogo sessions",
5
5
  "keywords": [
6
6
  "fogo",
@@ -39,6 +39,6 @@
39
39
  "bn.js": "^5.1.2",
40
40
  "bs58": "^6.0.0",
41
41
  "zod": "^3.25.62",
42
- "@fogo/sessions-idls": "^0.0.6"
42
+ "@fogo/sessions-idls": "^0.0.7"
43
43
  }
44
44
  }
package/cjs/adapter.d.ts DELETED
@@ -1,37 +0,0 @@
1
- import type { Transaction, Instruction, TransactionWithLifetime } from "@solana/kit";
2
- import type { Connection, TransactionError } from "@solana/web3.js";
3
- import { PublicKey, TransactionInstruction, VersionedTransaction } from "@solana/web3.js";
4
- export type SessionAdapter = {
5
- chainId: string;
6
- connection: Connection;
7
- payer: PublicKey;
8
- domain: string;
9
- sendTransaction: (sessionKey: CryptoKeyPair | undefined, instructions: (TransactionInstruction | Instruction)[] | VersionedTransaction | (Transaction & TransactionWithLifetime)) => Promise<TransactionResult>;
10
- };
11
- export declare enum TransactionResultType {
12
- Success = 0,
13
- Failed = 1
14
- }
15
- declare const TransactionResult: {
16
- Success: (signature: string) => {
17
- type: TransactionResultType.Success;
18
- signature: string;
19
- };
20
- Failed: (signature: string, error: TransactionError) => {
21
- type: TransactionResultType.Failed;
22
- signature: string;
23
- error: TransactionError;
24
- };
25
- };
26
- export type TransactionResult = ReturnType<(typeof TransactionResult)[keyof typeof TransactionResult]>;
27
- export declare const createSolanaWalletAdapter: (options: {
28
- connection: Connection;
29
- addressLookupTableAddress?: string | undefined;
30
- domain?: string | undefined;
31
- } & ({
32
- paymaster?: string | URL | undefined;
33
- } | {
34
- sendToPaymaster: (transaction: Transaction) => Promise<TransactionResult>;
35
- sponsor: PublicKey;
36
- })) => Promise<SessionAdapter>;
37
- export {};