@fogo/sessions-sdk 0.0.17 → 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 {};
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSessionConnection = exports.TransactionResultType = exports.DEFAULT_PAYMASTER = exports.DEFAULT_RPC = exports.Network = void 0;
4
+ const compat_1 = require("@solana/compat");
5
+ const kit_1 = require("@solana/kit");
6
+ const web3_js_1 = require("@solana/web3.js");
7
+ 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 = {}));
13
+ exports.DEFAULT_RPC = {
14
+ [Network.Testnet]: "https://testnet.fogo.io",
15
+ [Network.Mainnet]: "https://mainnet.fogo.io",
16
+ };
17
+ exports.DEFAULT_PAYMASTER = {
18
+ [Network.Testnet]: "https://paymaster.fogo.io",
19
+ [Network.Mainnet]: "https://paymaster.dourolabs.app",
20
+ };
21
+ const DEFAULT_ADDRESS_LOOKUP_TABLE_ADDRESS = {
22
+ [Network.Testnet]: "B8cUjJMqaWWTNNSTXBmeptjWswwCH1gTSCRYv4nu7kJW",
23
+ [Network.Mainnet]: undefined,
24
+ };
25
+ var TransactionResultType;
26
+ (function (TransactionResultType) {
27
+ TransactionResultType[TransactionResultType["Success"] = 0] = "Success";
28
+ TransactionResultType[TransactionResultType["Failed"] = 1] = "Failed";
29
+ })(TransactionResultType || (exports.TransactionResultType = TransactionResultType = {}));
30
+ const TransactionResult = {
31
+ Success: (signature) => ({
32
+ type: TransactionResultType.Success,
33
+ signature,
34
+ }),
35
+ Failed: (signature, error) => ({
36
+ type: TransactionResultType.Failed,
37
+ signature,
38
+ error,
39
+ }),
40
+ };
41
+ const createSessionConnection = (options) => {
42
+ // For some reason, typescript is unable to narrow this type even though it's
43
+ // obvious that `rpc` can only be `undefined` if `network` is defined. I
44
+ // don't like the non-null assertion, but here we can guarantee it's safe (and
45
+ // typescript really should be able to narrow this...)
46
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
47
+ const rpcUrl = (options.rpc ?? exports.DEFAULT_RPC[options.network]).toString();
48
+ const rpc = (0, kit_1.createSolanaRpc)(rpcUrl);
49
+ const connection = new web3_js_1.Connection(rpcUrl, "confirmed");
50
+ return {
51
+ rpc,
52
+ connection,
53
+ sendToPaymaster: async (domain, sponsor, addressLookupTables, sessionKey, instructions) => {
54
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
55
+ const transaction = await buildTransaction(latestBlockhash, sessionKey, sponsor, instructions, addressLookupTables);
56
+ return sendToPaymaster(options, domain, transaction);
57
+ },
58
+ getSponsor: (domain) => getSponsor(options, domain),
59
+ getAddressLookupTables: (addressLookupTableAddress) => getAddressLookupTables(options, connection, addressLookupTableAddress),
60
+ };
61
+ };
62
+ exports.createSessionConnection = createSessionConnection;
63
+ const sendToPaymaster = async (options, domain, transaction) => {
64
+ if (options.sendToPaymaster === undefined) {
65
+ const url = new URL("/api/sponsor_and_send", options.paymaster ?? exports.DEFAULT_PAYMASTER[options.network]);
66
+ url.searchParams.set("domain", domain);
67
+ const response = await fetch(url, {
68
+ method: "POST",
69
+ headers: {
70
+ "Content-Type": "application/json",
71
+ },
72
+ body: JSON.stringify({
73
+ transaction: (0, kit_1.getBase64EncodedWireTransaction)(transaction),
74
+ }),
75
+ });
76
+ if (response.status === 200) {
77
+ return sponsorAndSendResponseSchema.parse(await response.json());
78
+ }
79
+ else {
80
+ throw new PaymasterResponseError(response.status, await response.text());
81
+ }
82
+ }
83
+ else {
84
+ return options.sendToPaymaster(transaction);
85
+ }
86
+ };
87
+ const buildTransaction = async (latestBlockhash, sessionKey, sponsor, instructions, addressLookupTables) => {
88
+ const sessionKeySigner = sessionKey
89
+ ? await (0, kit_1.createSignerFromKeyPair)(sessionKey)
90
+ : undefined;
91
+ if (Array.isArray(instructions)) {
92
+ 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
93
+ ? (0, compat_1.fromLegacyTransactionInstruction)(instruction)
94
+ : instruction), tx), (tx) => (0, kit_1.compressTransactionMessageUsingAddressLookupTables)(tx, Object.fromEntries(addressLookupTables?.map((table) => [
95
+ (0, compat_1.fromLegacyPublicKey)(table.key),
96
+ table.state.addresses.map((address) => (0, compat_1.fromLegacyPublicKey)(address)),
97
+ ]) ?? [])), (tx) => sessionKeySigner === undefined
98
+ ? tx
99
+ : (0, kit_1.addSignersToTransactionMessage)([sessionKeySigner], tx)));
100
+ }
101
+ else {
102
+ const tx = instructions instanceof web3_js_1.VersionedTransaction
103
+ ? (0, compat_1.fromVersionedTransaction)(instructions) // VersionedTransaction has a lifetime so it's fine to cast it so we can call partiallySignTransaction
104
+ : instructions;
105
+ return sessionKey === undefined
106
+ ? tx
107
+ : (0, kit_1.partiallySignTransaction)([sessionKey], tx);
108
+ }
109
+ };
110
+ const sponsorAndSendResponseSchema = zod_1.z
111
+ .discriminatedUnion("type", [
112
+ zod_1.z.object({
113
+ type: zod_1.z.literal("success"),
114
+ signature: zod_1.z.string(),
115
+ }),
116
+ zod_1.z.object({
117
+ type: zod_1.z.literal("failed"),
118
+ signature: zod_1.z.string(),
119
+ error: zod_1.z.object({
120
+ InstructionError: zod_1.z.tuple([zod_1.z.number(), zod_1.z.unknown()]),
121
+ }),
122
+ }),
123
+ ])
124
+ .transform((data) => {
125
+ return data.type === "success"
126
+ ? TransactionResult.Success(data.signature)
127
+ : TransactionResult.Failed(data.signature, data.error);
128
+ });
129
+ const getSponsor = async (options, domain) => {
130
+ if (options.sponsor === undefined) {
131
+ const url = new URL("/api/sponsor_pubkey", options.paymaster ?? exports.DEFAULT_PAYMASTER[options.network]);
132
+ url.searchParams.set("domain", domain);
133
+ const response = await fetch(url);
134
+ if (response.status === 200) {
135
+ return new web3_js_1.PublicKey(zod_1.z.string().parse(await response.text()));
136
+ }
137
+ else {
138
+ throw new PaymasterResponseError(response.status, await response.text());
139
+ }
140
+ }
141
+ else {
142
+ return options.sponsor;
143
+ }
144
+ };
145
+ const getAddressLookupTables = async (options, connection, addressLookupTableAddress) => {
146
+ const altAddress = addressLookupTableAddress ??
147
+ (options.network === undefined
148
+ ? undefined
149
+ : DEFAULT_ADDRESS_LOOKUP_TABLE_ADDRESS[options.network]);
150
+ if (altAddress) {
151
+ const addressLookupTableResult = await connection.getAddressLookupTable(new web3_js_1.PublicKey(altAddress));
152
+ return addressLookupTableResult.value
153
+ ? [addressLookupTableResult.value]
154
+ : undefined;
155
+ }
156
+ else {
157
+ return;
158
+ }
159
+ };
160
+ class PaymasterResponseError extends Error {
161
+ constructor(statusCode, message) {
162
+ super(`Paymaster sent a ${statusCode.toString()} response: ${message}`);
163
+ this.name = "PaymasterResponseError";
164
+ }
165
+ }
package/cjs/context.d.ts CHANGED
@@ -1,40 +1,15 @@
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 SessionContext = {
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]>;
1
+ import { Connection as Web3Connection } from "@solana/web3.js";
2
+ import type { Connection } from "./connection.js";
27
3
  export declare const createSessionContext: (options: {
28
4
  connection: Connection;
29
5
  addressLookupTableAddress?: string | undefined;
30
6
  domain?: string | undefined;
31
- } & ({
32
- paymaster?: string | URL | undefined;
33
- sendToPaymaster?: undefined;
34
- sponsor?: undefined;
35
- } | {
36
- paymaster?: undefined;
37
- sendToPaymaster: (transaction: Transaction) => Promise<TransactionResult>;
38
- sponsor: PublicKey;
39
- })) => Promise<SessionContext>;
40
- export {};
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/cjs/context.js CHANGED
@@ -1,137 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createSessionContext = exports.TransactionResultType = void 0;
3
+ exports.createSessionContext = void 0;
4
4
  const anchor_1 = require("@coral-xyz/anchor");
5
5
  const sessions_idls_1 = require("@fogo/sessions-idls");
6
- const compat_1 = require("@solana/compat");
7
- const kit_1 = require("@solana/kit");
8
6
  const web3_js_1 = require("@solana/web3.js");
9
- const zod_1 = require("zod");
10
7
  // eslint-disable-next-line unicorn/no-typeof-undefined
11
8
  const IS_BROWSER = typeof globalThis.window !== "undefined";
12
- const DEFAULT_PAYMASTER = "https://paymaster.fogo.io";
13
- const DEFAULT_ADDRESS_LOOKUP_TABLE_ADDRESS = "B8cUjJMqaWWTNNSTXBmeptjWswwCH1gTSCRYv4nu7kJW";
14
- var TransactionResultType;
15
- (function (TransactionResultType) {
16
- TransactionResultType[TransactionResultType["Success"] = 0] = "Success";
17
- TransactionResultType[TransactionResultType["Failed"] = 1] = "Failed";
18
- })(TransactionResultType || (exports.TransactionResultType = TransactionResultType = {}));
19
- const TransactionResult = {
20
- Success: (signature) => ({
21
- type: TransactionResultType.Success,
22
- signature,
23
- }),
24
- Failed: (signature, error) => ({
25
- type: TransactionResultType.Failed,
26
- signature,
27
- error,
28
- }),
29
- };
30
9
  const createSessionContext = async (options) => {
31
- const addressLookupTables = await getAddressLookupTables(options.connection, options.addressLookupTableAddress);
10
+ const addressLookupTables = await options.connection.getAddressLookupTables(options.addressLookupTableAddress);
32
11
  const domain = getDomain(options.domain);
33
- const sponsor = await getSponsor(options, domain);
12
+ const sponsor = await options.connection.getSponsor(domain);
34
13
  return {
35
- connection: options.connection,
36
- payer: sponsor,
37
- chainId: await fetchChainId(options.connection),
14
+ chainId: await fetchChainId(options.connection.connection),
38
15
  domain: getDomain(options.domain),
39
- sendTransaction: async (sessionKey, instructions) => {
40
- const rpc = (0, kit_1.createSolanaRpc)(options.connection.rpcEndpoint);
41
- const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
42
- return await sendToPaymaster(options, await buildTransaction(latestBlockhash, sessionKey, sponsor, instructions, addressLookupTables), domain);
43
- },
16
+ payer: sponsor,
17
+ connection: options.connection.connection,
18
+ rpc: options.connection.rpc,
19
+ sendTransaction: (sessionKey, instructions) => options.connection.sendToPaymaster(domain, sponsor, addressLookupTables, sessionKey, instructions),
44
20
  };
45
21
  };
46
22
  exports.createSessionContext = createSessionContext;
47
- const buildTransaction = async (latestBlockhash, sessionKey, sponsor, instructions, addressLookupTables) => {
48
- const sessionKeySigner = sessionKey
49
- ? await (0, kit_1.createSignerFromKeyPair)(sessionKey)
50
- : undefined;
51
- if (Array.isArray(instructions)) {
52
- 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
53
- ? (0, compat_1.fromLegacyTransactionInstruction)(instruction)
54
- : instruction), tx), (tx) => (0, kit_1.compressTransactionMessageUsingAddressLookupTables)(tx, Object.fromEntries(addressLookupTables?.map((table) => [
55
- (0, compat_1.fromLegacyPublicKey)(table.key),
56
- table.state.addresses.map((address) => (0, compat_1.fromLegacyPublicKey)(address)),
57
- ]) ?? [])), (tx) => sessionKeySigner === undefined
58
- ? tx
59
- : (0, kit_1.addSignersToTransactionMessage)([sessionKeySigner], tx)));
60
- }
61
- else {
62
- const tx = instructions instanceof web3_js_1.VersionedTransaction
63
- ? (0, compat_1.fromVersionedTransaction)(instructions) // VersionedTransaction has a lifetime so it's fine to cast it so we can call partiallySignTransaction
64
- : instructions;
65
- return sessionKey === undefined
66
- ? tx
67
- : (0, kit_1.partiallySignTransaction)([sessionKey], tx);
68
- }
69
- };
70
- const getSponsor = async (options, domain) => {
71
- if (options.sponsor === undefined) {
72
- const url = new URL("/api/sponsor_pubkey", options.paymaster ?? DEFAULT_PAYMASTER);
73
- url.searchParams.set("domain", domain);
74
- const response = await fetch(url);
75
- if (response.status === 200) {
76
- return new web3_js_1.PublicKey(zod_1.z.string().parse(await response.text()));
77
- }
78
- else {
79
- throw new PaymasterResponseError(response.status, await response.text());
80
- }
81
- }
82
- else {
83
- return options.sponsor;
84
- }
85
- };
86
- const sponsorAndSendResponseSchema = zod_1.z
87
- .discriminatedUnion("type", [
88
- zod_1.z.object({
89
- type: zod_1.z.literal("success"),
90
- signature: zod_1.z.string(),
91
- }),
92
- zod_1.z.object({
93
- type: zod_1.z.literal("failed"),
94
- signature: zod_1.z.string(),
95
- error: zod_1.z.object({
96
- InstructionError: zod_1.z.tuple([zod_1.z.number(), zod_1.z.unknown()]),
97
- }),
98
- }),
99
- ])
100
- .transform((data) => {
101
- return data.type === "success"
102
- ? TransactionResult.Success(data.signature)
103
- : TransactionResult.Failed(data.signature, data.error);
104
- });
105
- const sendToPaymaster = async (options, transaction, domain) => {
106
- if (options.sendToPaymaster === undefined) {
107
- const url = new URL("/api/sponsor_and_send", options.paymaster ?? DEFAULT_PAYMASTER);
108
- url.searchParams.set("domain", domain);
109
- const response = await fetch(url, {
110
- method: "POST",
111
- headers: {
112
- "Content-Type": "application/json",
113
- },
114
- body: JSON.stringify({
115
- transaction: (0, kit_1.getBase64EncodedWireTransaction)(transaction),
116
- }),
117
- });
118
- if (response.status === 200) {
119
- return sponsorAndSendResponseSchema.parse(await response.json());
120
- }
121
- else {
122
- throw new PaymasterResponseError(response.status, await response.text());
123
- }
124
- }
125
- else {
126
- return options.sendToPaymaster(transaction);
127
- }
128
- };
129
- const getAddressLookupTables = async (connection, addressLookupTableAddress = DEFAULT_ADDRESS_LOOKUP_TABLE_ADDRESS) => {
130
- const addressLookupTableResult = await connection.getAddressLookupTable(new web3_js_1.PublicKey(addressLookupTableAddress));
131
- return addressLookupTableResult.value
132
- ? [addressLookupTableResult.value]
133
- : undefined;
134
- };
135
23
  const fetchChainId = async (connection) => {
136
24
  const chainIdProgram = new sessions_idls_1.ChainIdProgram(new anchor_1.AnchorProvider(connection, { publicKey: new web3_js_1.Keypair().publicKey }, {})); // We mock the wallet because we don't need to sign anything
137
25
  const { chainIdAccount: chainIdAddress } = await chainIdProgram.methods
@@ -157,12 +45,6 @@ const getDomain = (requestedDomain) => {
157
45
  return requestedDomain;
158
46
  }
159
47
  };
160
- class PaymasterResponseError extends Error {
161
- constructor(statusCode, message) {
162
- super(`Paymaster sent a ${statusCode.toString()} response: ${message}`);
163
- this.name = "PaymasterResponseError";
164
- }
165
- }
166
48
  class NoChainIdAddressError extends Error {
167
49
  constructor() {
168
50
  super("Failed to derive chain ID address");
package/cjs/index.d.ts CHANGED
@@ -2,8 +2,10 @@ 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 { SessionContext, TransactionResult } from "./context.js";
6
- export { createSessionContext, TransactionResultType, type SessionContext, type TransactionResult, } from "./context.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
10
  context: SessionContext;
9
11
  walletPublicKey: PublicKey;
package/cjs/index.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.verifyLogInToken = exports.createLogInToken = exports.sendTransfer = exports.SessionResultType = exports.getDomainRecordAddress = exports.AuthorizedTokens = exports.AuthorizedProgramsType = exports.getSessionAccount = exports.reestablishSession = exports.revokeSession = exports.replaceSession = exports.establishSession = exports.TransactionResultType = exports.createSessionContext = void 0;
6
+ exports.verifyLogInToken = exports.createLogInToken = exports.sendTransfer = exports.SessionResultType = exports.getDomainRecordAddress = exports.AuthorizedTokens = exports.AuthorizedProgramsType = exports.getSessionAccount = exports.reestablishSession = exports.revokeSession = exports.replaceSession = exports.establishSession = exports.createSessionConnection = exports.TransactionResultType = exports.Network = exports.createSessionContext = void 0;
7
7
  const anchor_1 = require("@coral-xyz/anchor");
8
8
  const sessions_idls_1 = require("@fogo/sessions-idls");
9
9
  const mpl_token_metadata_1 = require("@metaplex-foundation/mpl-token-metadata");
@@ -17,11 +17,14 @@ const web3_js_1 = require("@solana/web3.js");
17
17
  const bn_js_1 = __importDefault(require("bn.js"));
18
18
  const bs58_1 = __importDefault(require("bs58"));
19
19
  const zod_1 = require("zod");
20
- const context_js_1 = require("./context.js");
20
+ const connection_js_1 = require("./connection.js");
21
21
  const crypto_js_1 = require("./crypto.js");
22
- var context_js_2 = require("./context.js");
23
- Object.defineProperty(exports, "createSessionContext", { enumerable: true, get: function () { return context_js_2.createSessionContext; } });
24
- Object.defineProperty(exports, "TransactionResultType", { enumerable: true, get: function () { return context_js_2.TransactionResultType; } });
22
+ var context_js_1 = require("./context.js");
23
+ Object.defineProperty(exports, "createSessionContext", { enumerable: true, get: function () { return context_js_1.createSessionContext; } });
24
+ var connection_js_2 = require("./connection.js");
25
+ Object.defineProperty(exports, "Network", { enumerable: true, get: function () { return connection_js_2.Network; } });
26
+ Object.defineProperty(exports, "TransactionResultType", { enumerable: true, get: function () { return connection_js_2.TransactionResultType; } });
27
+ Object.defineProperty(exports, "createSessionConnection", { enumerable: true, get: function () { return connection_js_2.createSessionConnection; } });
25
28
  const MESSAGE_HEADER = `Fogo Sessions:
26
29
  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.
27
30
  `;
@@ -61,13 +64,13 @@ exports.establishSession = establishSession;
61
64
  const sendSessionEstablishTransaction = async (options, sessionKey, instructions) => {
62
65
  const result = await options.context.sendTransaction(sessionKey, instructions);
63
66
  switch (result.type) {
64
- case context_js_1.TransactionResultType.Success: {
67
+ case connection_js_1.TransactionResultType.Success: {
65
68
  const session = await createSession(options.context, options.walletPublicKey, sessionKey);
66
69
  return session
67
70
  ? EstablishSessionResult.Success(result.signature, session)
68
71
  : EstablishSessionResult.Failed(result.signature, new Error("Transaction succeeded, but the session was not created"));
69
72
  }
70
- case context_js_1.TransactionResultType.Failed: {
73
+ case connection_js_1.TransactionResultType.Failed: {
71
74
  return EstablishSessionResult.Failed(result.signature, result.error);
72
75
  }
73
76
  }
@@ -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 {};
@@ -0,0 +1,161 @@
1
+ import { fromLegacyPublicKey, fromLegacyTransactionInstruction, fromVersionedTransaction, } from "@solana/compat";
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";
4
+ import { z } from "zod";
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
+ };
22
+ export var TransactionResultType;
23
+ (function (TransactionResultType) {
24
+ TransactionResultType[TransactionResultType["Success"] = 0] = "Success";
25
+ TransactionResultType[TransactionResultType["Failed"] = 1] = "Failed";
26
+ })(TransactionResultType || (TransactionResultType = {}));
27
+ const TransactionResult = {
28
+ Success: (signature) => ({
29
+ type: TransactionResultType.Success,
30
+ signature,
31
+ }),
32
+ Failed: (signature, error) => ({
33
+ type: TransactionResultType.Failed,
34
+ signature,
35
+ error,
36
+ }),
37
+ };
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");
47
+ return {
48
+ rpc,
49
+ connection,
50
+ sendToPaymaster: async (domain, sponsor, addressLookupTables, sessionKey, instructions) => {
51
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
52
+ const transaction = await buildTransaction(latestBlockhash, sessionKey, sponsor, instructions, addressLookupTables);
53
+ return sendToPaymaster(options, domain, transaction);
54
+ },
55
+ getSponsor: (domain) => getSponsor(options, domain),
56
+ getAddressLookupTables: (addressLookupTableAddress) => getAddressLookupTables(options, connection, addressLookupTableAddress),
57
+ };
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
+ };
83
+ const buildTransaction = async (latestBlockhash, sessionKey, sponsor, instructions, addressLookupTables) => {
84
+ const sessionKeySigner = sessionKey
85
+ ? await createSignerFromKeyPair(sessionKey)
86
+ : undefined;
87
+ if (Array.isArray(instructions)) {
88
+ return partiallySignTransactionMessageWithSigners(pipe(createTransactionMessage({ version: 0 }), (tx) => setTransactionMessageFeePayer(fromLegacyPublicKey(sponsor), tx), (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), (tx) => appendTransactionMessageInstructions(instructions.map((instruction) => instruction instanceof TransactionInstruction
89
+ ? fromLegacyTransactionInstruction(instruction)
90
+ : instruction), tx), (tx) => compressTransactionMessageUsingAddressLookupTables(tx, Object.fromEntries(addressLookupTables?.map((table) => [
91
+ fromLegacyPublicKey(table.key),
92
+ table.state.addresses.map((address) => fromLegacyPublicKey(address)),
93
+ ]) ?? [])), (tx) => sessionKeySigner === undefined
94
+ ? tx
95
+ : addSignersToTransactionMessage([sessionKeySigner], tx)));
96
+ }
97
+ else {
98
+ const tx = instructions instanceof VersionedTransaction
99
+ ? fromVersionedTransaction(instructions) // VersionedTransaction has a lifetime so it's fine to cast it so we can call partiallySignTransaction
100
+ : instructions;
101
+ return sessionKey === undefined
102
+ ? tx
103
+ : partiallySignTransaction([sessionKey], tx);
104
+ }
105
+ };
106
+ const sponsorAndSendResponseSchema = z
107
+ .discriminatedUnion("type", [
108
+ z.object({
109
+ type: z.literal("success"),
110
+ signature: z.string(),
111
+ }),
112
+ z.object({
113
+ type: z.literal("failed"),
114
+ signature: z.string(),
115
+ error: z.object({
116
+ InstructionError: z.tuple([z.number(), z.unknown()]),
117
+ }),
118
+ }),
119
+ ])
120
+ .transform((data) => {
121
+ return data.type === "success"
122
+ ? TransactionResult.Success(data.signature)
123
+ : TransactionResult.Failed(data.signature, data.error);
124
+ });
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]);
128
+ url.searchParams.set("domain", domain);
129
+ const response = await fetch(url);
130
+ if (response.status === 200) {
131
+ return new PublicKey(z.string().parse(await response.text()));
132
+ }
133
+ else {
134
+ throw new PaymasterResponseError(response.status, await response.text());
135
+ }
136
+ }
137
+ else {
138
+ return options.sponsor;
139
+ }
140
+ };
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
+ }
152
+ else {
153
+ return;
154
+ }
155
+ };
156
+ class PaymasterResponseError extends Error {
157
+ constructor(statusCode, message) {
158
+ super(`Paymaster sent a ${statusCode.toString()} response: ${message}`);
159
+ this.name = "PaymasterResponseError";
160
+ }
161
+ }
package/esm/context.d.ts CHANGED
@@ -1,40 +1,15 @@
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 SessionContext = {
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]>;
1
+ import { Connection as Web3Connection } from "@solana/web3.js";
2
+ import type { Connection } from "./connection.js";
27
3
  export declare const createSessionContext: (options: {
28
4
  connection: Connection;
29
5
  addressLookupTableAddress?: string | undefined;
30
6
  domain?: string | undefined;
31
- } & ({
32
- paymaster?: string | URL | undefined;
33
- sendToPaymaster?: undefined;
34
- sponsor?: undefined;
35
- } | {
36
- paymaster?: undefined;
37
- sendToPaymaster: (transaction: Transaction) => Promise<TransactionResult>;
38
- sponsor: PublicKey;
39
- })) => Promise<SessionContext>;
40
- export {};
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 CHANGED
@@ -1,133 +1,21 @@
1
1
  import { AnchorProvider } from "@coral-xyz/anchor";
2
2
  import { ChainIdProgram } from "@fogo/sessions-idls";
3
- 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";
6
- import { z } from "zod";
3
+ import { Connection as Web3Connection, Keypair } from "@solana/web3.js";
7
4
  // eslint-disable-next-line unicorn/no-typeof-undefined
8
5
  const IS_BROWSER = typeof globalThis.window !== "undefined";
9
- const DEFAULT_PAYMASTER = "https://paymaster.fogo.io";
10
- const DEFAULT_ADDRESS_LOOKUP_TABLE_ADDRESS = "B8cUjJMqaWWTNNSTXBmeptjWswwCH1gTSCRYv4nu7kJW";
11
- export var TransactionResultType;
12
- (function (TransactionResultType) {
13
- TransactionResultType[TransactionResultType["Success"] = 0] = "Success";
14
- TransactionResultType[TransactionResultType["Failed"] = 1] = "Failed";
15
- })(TransactionResultType || (TransactionResultType = {}));
16
- const TransactionResult = {
17
- Success: (signature) => ({
18
- type: TransactionResultType.Success,
19
- signature,
20
- }),
21
- Failed: (signature, error) => ({
22
- type: TransactionResultType.Failed,
23
- signature,
24
- error,
25
- }),
26
- };
27
6
  export const createSessionContext = async (options) => {
28
- const addressLookupTables = await getAddressLookupTables(options.connection, options.addressLookupTableAddress);
7
+ const addressLookupTables = await options.connection.getAddressLookupTables(options.addressLookupTableAddress);
29
8
  const domain = getDomain(options.domain);
30
- const sponsor = await getSponsor(options, domain);
9
+ const sponsor = await options.connection.getSponsor(domain);
31
10
  return {
32
- connection: options.connection,
33
- payer: sponsor,
34
- chainId: await fetchChainId(options.connection),
11
+ chainId: await fetchChainId(options.connection.connection),
35
12
  domain: getDomain(options.domain),
36
- sendTransaction: async (sessionKey, instructions) => {
37
- const rpc = createSolanaRpc(options.connection.rpcEndpoint);
38
- const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
39
- return await sendToPaymaster(options, await buildTransaction(latestBlockhash, sessionKey, sponsor, instructions, addressLookupTables), domain);
40
- },
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),
41
17
  };
42
18
  };
43
- const buildTransaction = async (latestBlockhash, sessionKey, sponsor, instructions, addressLookupTables) => {
44
- const sessionKeySigner = sessionKey
45
- ? await createSignerFromKeyPair(sessionKey)
46
- : undefined;
47
- if (Array.isArray(instructions)) {
48
- return partiallySignTransactionMessageWithSigners(pipe(createTransactionMessage({ version: 0 }), (tx) => setTransactionMessageFeePayer(fromLegacyPublicKey(sponsor), tx), (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), (tx) => appendTransactionMessageInstructions(instructions.map((instruction) => instruction instanceof TransactionInstruction
49
- ? fromLegacyTransactionInstruction(instruction)
50
- : instruction), tx), (tx) => compressTransactionMessageUsingAddressLookupTables(tx, Object.fromEntries(addressLookupTables?.map((table) => [
51
- fromLegacyPublicKey(table.key),
52
- table.state.addresses.map((address) => fromLegacyPublicKey(address)),
53
- ]) ?? [])), (tx) => sessionKeySigner === undefined
54
- ? tx
55
- : addSignersToTransactionMessage([sessionKeySigner], tx)));
56
- }
57
- else {
58
- const tx = instructions instanceof VersionedTransaction
59
- ? fromVersionedTransaction(instructions) // VersionedTransaction has a lifetime so it's fine to cast it so we can call partiallySignTransaction
60
- : instructions;
61
- return sessionKey === undefined
62
- ? tx
63
- : partiallySignTransaction([sessionKey], tx);
64
- }
65
- };
66
- const getSponsor = async (options, domain) => {
67
- if (options.sponsor === undefined) {
68
- const url = new URL("/api/sponsor_pubkey", options.paymaster ?? DEFAULT_PAYMASTER);
69
- url.searchParams.set("domain", domain);
70
- const response = await fetch(url);
71
- if (response.status === 200) {
72
- return new PublicKey(z.string().parse(await response.text()));
73
- }
74
- else {
75
- throw new PaymasterResponseError(response.status, await response.text());
76
- }
77
- }
78
- else {
79
- return options.sponsor;
80
- }
81
- };
82
- const sponsorAndSendResponseSchema = z
83
- .discriminatedUnion("type", [
84
- z.object({
85
- type: z.literal("success"),
86
- signature: z.string(),
87
- }),
88
- z.object({
89
- type: z.literal("failed"),
90
- signature: z.string(),
91
- error: z.object({
92
- InstructionError: z.tuple([z.number(), z.unknown()]),
93
- }),
94
- }),
95
- ])
96
- .transform((data) => {
97
- return data.type === "success"
98
- ? TransactionResult.Success(data.signature)
99
- : TransactionResult.Failed(data.signature, data.error);
100
- });
101
- const sendToPaymaster = async (options, transaction, domain) => {
102
- if (options.sendToPaymaster === undefined) {
103
- const url = new URL("/api/sponsor_and_send", options.paymaster ?? DEFAULT_PAYMASTER);
104
- url.searchParams.set("domain", domain);
105
- const response = await fetch(url, {
106
- method: "POST",
107
- headers: {
108
- "Content-Type": "application/json",
109
- },
110
- body: JSON.stringify({
111
- transaction: getBase64EncodedWireTransaction(transaction),
112
- }),
113
- });
114
- if (response.status === 200) {
115
- return sponsorAndSendResponseSchema.parse(await response.json());
116
- }
117
- else {
118
- throw new PaymasterResponseError(response.status, await response.text());
119
- }
120
- }
121
- else {
122
- return options.sendToPaymaster(transaction);
123
- }
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
19
  const fetchChainId = async (connection) => {
132
20
  const chainIdProgram = new ChainIdProgram(new AnchorProvider(connection, { publicKey: new Keypair().publicKey }, {})); // We mock the wallet because we don't need to sign anything
133
21
  const { chainIdAccount: chainIdAddress } = await chainIdProgram.methods
@@ -153,12 +41,6 @@ const getDomain = (requestedDomain) => {
153
41
  return requestedDomain;
154
42
  }
155
43
  };
156
- class PaymasterResponseError extends Error {
157
- constructor(statusCode, message) {
158
- super(`Paymaster sent a ${statusCode.toString()} response: ${message}`);
159
- this.name = "PaymasterResponseError";
160
- }
161
- }
162
44
  class NoChainIdAddressError extends Error {
163
45
  constructor() {
164
46
  super("Failed to derive chain ID address");
package/esm/index.d.ts CHANGED
@@ -2,8 +2,10 @@ 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 { SessionContext, TransactionResult } from "./context.js";
6
- export { createSessionContext, TransactionResultType, type SessionContext, type TransactionResult, } from "./context.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
10
  context: SessionContext;
9
11
  walletPublicKey: 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 "./context.js";
14
+ import { TransactionResultType } from "./connection.js";
15
15
  import { importKey, signMessageWithKey, verifyMessageWithKey, } from "./crypto.js";
16
- export { createSessionContext, TransactionResultType, } from "./context.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
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fogo/sessions-sdk",
3
- "version": "0.0.17",
3
+ "version": "0.0.18",
4
4
  "description": "A set of utilities for integrating with Fogo sessions",
5
5
  "keywords": [
6
6
  "fogo",