@fogo/sessions-sdk 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/index.d.ts +251 -6
- package/cjs/index.js +169 -58
- package/cjs/paymaster.js +6 -10
- package/esm/index.d.ts +251 -6
- package/esm/index.js +165 -58
- package/esm/paymaster.js +7 -11
- package/package.json +3 -2
package/cjs/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import type { TransactionError } from "@solana/web3.js";
|
|
1
|
+
import type { TransactionError, Connection } from "@solana/web3.js";
|
|
2
2
|
import { PublicKey } from "@solana/web3.js";
|
|
3
|
+
import BN from "bn.js";
|
|
4
|
+
import { z } from "zod";
|
|
3
5
|
import type { SessionAdapter, TransactionResult } from "./adapter.js";
|
|
4
6
|
export { type SessionAdapter, type TransactionResult, TransactionResultType, createSolanaWalletAdapter, } from "./adapter.js";
|
|
5
7
|
type EstablishSessionOptions = {
|
|
@@ -7,19 +9,261 @@ type EstablishSessionOptions = {
|
|
|
7
9
|
walletPublicKey: PublicKey;
|
|
8
10
|
signMessage: (message: Uint8Array) => Promise<Uint8Array>;
|
|
9
11
|
expires: Date;
|
|
10
|
-
limits: Map<PublicKey, bigint>;
|
|
11
12
|
extra?: string | undefined;
|
|
12
|
-
}
|
|
13
|
+
} & ({
|
|
14
|
+
limits?: Map<PublicKey, bigint>;
|
|
15
|
+
unlimited?: false;
|
|
16
|
+
} | {
|
|
17
|
+
unlimited: true;
|
|
18
|
+
});
|
|
13
19
|
export declare const establishSession: (options: EstablishSessionOptions) => Promise<EstablishSessionResult>;
|
|
14
20
|
export declare const replaceSession: (options: {
|
|
15
21
|
adapter: SessionAdapter;
|
|
16
22
|
session: Session;
|
|
17
23
|
signMessage: (message: Uint8Array) => Promise<Uint8Array>;
|
|
18
24
|
expires: Date;
|
|
19
|
-
limits: Map<PublicKey, bigint>;
|
|
20
25
|
extra?: string | undefined;
|
|
21
|
-
}
|
|
22
|
-
|
|
26
|
+
} & ({
|
|
27
|
+
limits?: Map<PublicKey, bigint>;
|
|
28
|
+
unlimited?: false;
|
|
29
|
+
} | {
|
|
30
|
+
unlimited: true;
|
|
31
|
+
})) => Promise<EstablishSessionResult>;
|
|
32
|
+
export declare const reestablishSession: (adapter: SessionAdapter, walletPublicKey: PublicKey, sessionKey: CryptoKeyPair) => Promise<Session | undefined>;
|
|
33
|
+
export declare const getSessionAccount: (connection: Connection, sessionPublicKey: PublicKey) => Promise<{
|
|
34
|
+
authorizedPrograms: {
|
|
35
|
+
type: AuthorizedProgramsType.All;
|
|
36
|
+
} | {
|
|
37
|
+
type: AuthorizedProgramsType.Specific;
|
|
38
|
+
programs: {
|
|
39
|
+
programId: PublicKey;
|
|
40
|
+
signerPda: PublicKey;
|
|
41
|
+
}[];
|
|
42
|
+
};
|
|
43
|
+
authorizedTokens: AuthorizedTokens;
|
|
44
|
+
expiration: Date;
|
|
45
|
+
extra: unknown;
|
|
46
|
+
major: number;
|
|
47
|
+
minor: number;
|
|
48
|
+
user: PublicKey;
|
|
49
|
+
} | undefined>;
|
|
50
|
+
declare const sessionInfoSchema: z.ZodEffects<z.ZodObject<{
|
|
51
|
+
session_info: z.ZodObject<{
|
|
52
|
+
authorized_programs: z.ZodUnion<[z.ZodObject<{
|
|
53
|
+
Specific: z.ZodObject<{
|
|
54
|
+
0: z.ZodArray<z.ZodObject<{
|
|
55
|
+
program_id: z.ZodType<PublicKey, z.ZodTypeDef, PublicKey>;
|
|
56
|
+
signer_pda: z.ZodType<PublicKey, z.ZodTypeDef, PublicKey>;
|
|
57
|
+
}, "strip", z.ZodTypeAny, {
|
|
58
|
+
program_id: PublicKey;
|
|
59
|
+
signer_pda: PublicKey;
|
|
60
|
+
}, {
|
|
61
|
+
program_id: PublicKey;
|
|
62
|
+
signer_pda: PublicKey;
|
|
63
|
+
}>, "many">;
|
|
64
|
+
}, "strip", z.ZodTypeAny, {
|
|
65
|
+
0: {
|
|
66
|
+
program_id: PublicKey;
|
|
67
|
+
signer_pda: PublicKey;
|
|
68
|
+
}[];
|
|
69
|
+
}, {
|
|
70
|
+
0: {
|
|
71
|
+
program_id: PublicKey;
|
|
72
|
+
signer_pda: PublicKey;
|
|
73
|
+
}[];
|
|
74
|
+
}>;
|
|
75
|
+
}, "strip", z.ZodTypeAny, {
|
|
76
|
+
Specific: {
|
|
77
|
+
0: {
|
|
78
|
+
program_id: PublicKey;
|
|
79
|
+
signer_pda: PublicKey;
|
|
80
|
+
}[];
|
|
81
|
+
};
|
|
82
|
+
}, {
|
|
83
|
+
Specific: {
|
|
84
|
+
0: {
|
|
85
|
+
program_id: PublicKey;
|
|
86
|
+
signer_pda: PublicKey;
|
|
87
|
+
}[];
|
|
88
|
+
};
|
|
89
|
+
}>, z.ZodObject<{
|
|
90
|
+
All: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
|
|
91
|
+
}, "strip", z.ZodTypeAny, {
|
|
92
|
+
All: {};
|
|
93
|
+
}, {
|
|
94
|
+
All: {};
|
|
95
|
+
}>]>;
|
|
96
|
+
authorized_tokens: z.ZodUnion<[z.ZodObject<{
|
|
97
|
+
Specific: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
|
|
98
|
+
}, "strip", z.ZodTypeAny, {
|
|
99
|
+
Specific: {};
|
|
100
|
+
}, {
|
|
101
|
+
Specific: {};
|
|
102
|
+
}>, z.ZodObject<{
|
|
103
|
+
All: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
|
|
104
|
+
}, "strip", z.ZodTypeAny, {
|
|
105
|
+
All: {};
|
|
106
|
+
}, {
|
|
107
|
+
All: {};
|
|
108
|
+
}>]>;
|
|
109
|
+
expiration: z.ZodType<BN, z.ZodTypeDef, BN>;
|
|
110
|
+
extra: z.ZodObject<{
|
|
111
|
+
0: z.ZodUnknown;
|
|
112
|
+
}, "strip", z.ZodTypeAny, {
|
|
113
|
+
0?: unknown;
|
|
114
|
+
}, {
|
|
115
|
+
0?: unknown;
|
|
116
|
+
}>;
|
|
117
|
+
major: z.ZodNumber;
|
|
118
|
+
minor: z.ZodNumber;
|
|
119
|
+
user: z.ZodType<PublicKey, z.ZodTypeDef, PublicKey>;
|
|
120
|
+
}, "strip", z.ZodTypeAny, {
|
|
121
|
+
authorized_programs: {
|
|
122
|
+
Specific: {
|
|
123
|
+
0: {
|
|
124
|
+
program_id: PublicKey;
|
|
125
|
+
signer_pda: PublicKey;
|
|
126
|
+
}[];
|
|
127
|
+
};
|
|
128
|
+
} | {
|
|
129
|
+
All: {};
|
|
130
|
+
};
|
|
131
|
+
authorized_tokens: {
|
|
132
|
+
Specific: {};
|
|
133
|
+
} | {
|
|
134
|
+
All: {};
|
|
135
|
+
};
|
|
136
|
+
expiration: BN;
|
|
137
|
+
extra: {
|
|
138
|
+
0?: unknown;
|
|
139
|
+
};
|
|
140
|
+
major: number;
|
|
141
|
+
minor: number;
|
|
142
|
+
user: PublicKey;
|
|
143
|
+
}, {
|
|
144
|
+
authorized_programs: {
|
|
145
|
+
Specific: {
|
|
146
|
+
0: {
|
|
147
|
+
program_id: PublicKey;
|
|
148
|
+
signer_pda: PublicKey;
|
|
149
|
+
}[];
|
|
150
|
+
};
|
|
151
|
+
} | {
|
|
152
|
+
All: {};
|
|
153
|
+
};
|
|
154
|
+
authorized_tokens: {
|
|
155
|
+
Specific: {};
|
|
156
|
+
} | {
|
|
157
|
+
All: {};
|
|
158
|
+
};
|
|
159
|
+
expiration: BN;
|
|
160
|
+
extra: {
|
|
161
|
+
0?: unknown;
|
|
162
|
+
};
|
|
163
|
+
major: number;
|
|
164
|
+
minor: number;
|
|
165
|
+
user: PublicKey;
|
|
166
|
+
}>;
|
|
167
|
+
}, "strip", z.ZodTypeAny, {
|
|
168
|
+
session_info: {
|
|
169
|
+
authorized_programs: {
|
|
170
|
+
Specific: {
|
|
171
|
+
0: {
|
|
172
|
+
program_id: PublicKey;
|
|
173
|
+
signer_pda: PublicKey;
|
|
174
|
+
}[];
|
|
175
|
+
};
|
|
176
|
+
} | {
|
|
177
|
+
All: {};
|
|
178
|
+
};
|
|
179
|
+
authorized_tokens: {
|
|
180
|
+
Specific: {};
|
|
181
|
+
} | {
|
|
182
|
+
All: {};
|
|
183
|
+
};
|
|
184
|
+
expiration: BN;
|
|
185
|
+
extra: {
|
|
186
|
+
0?: unknown;
|
|
187
|
+
};
|
|
188
|
+
major: number;
|
|
189
|
+
minor: number;
|
|
190
|
+
user: PublicKey;
|
|
191
|
+
};
|
|
192
|
+
}, {
|
|
193
|
+
session_info: {
|
|
194
|
+
authorized_programs: {
|
|
195
|
+
Specific: {
|
|
196
|
+
0: {
|
|
197
|
+
program_id: PublicKey;
|
|
198
|
+
signer_pda: PublicKey;
|
|
199
|
+
}[];
|
|
200
|
+
};
|
|
201
|
+
} | {
|
|
202
|
+
All: {};
|
|
203
|
+
};
|
|
204
|
+
authorized_tokens: {
|
|
205
|
+
Specific: {};
|
|
206
|
+
} | {
|
|
207
|
+
All: {};
|
|
208
|
+
};
|
|
209
|
+
expiration: BN;
|
|
210
|
+
extra: {
|
|
211
|
+
0?: unknown;
|
|
212
|
+
};
|
|
213
|
+
major: number;
|
|
214
|
+
minor: number;
|
|
215
|
+
user: PublicKey;
|
|
216
|
+
};
|
|
217
|
+
}>, {
|
|
218
|
+
authorizedPrograms: {
|
|
219
|
+
type: AuthorizedProgramsType.All;
|
|
220
|
+
} | {
|
|
221
|
+
type: AuthorizedProgramsType.Specific;
|
|
222
|
+
programs: {
|
|
223
|
+
programId: PublicKey;
|
|
224
|
+
signerPda: PublicKey;
|
|
225
|
+
}[];
|
|
226
|
+
};
|
|
227
|
+
authorizedTokens: AuthorizedTokens;
|
|
228
|
+
expiration: Date;
|
|
229
|
+
extra: unknown;
|
|
230
|
+
major: number;
|
|
231
|
+
minor: number;
|
|
232
|
+
user: PublicKey;
|
|
233
|
+
}, {
|
|
234
|
+
session_info: {
|
|
235
|
+
authorized_programs: {
|
|
236
|
+
Specific: {
|
|
237
|
+
0: {
|
|
238
|
+
program_id: PublicKey;
|
|
239
|
+
signer_pda: PublicKey;
|
|
240
|
+
}[];
|
|
241
|
+
};
|
|
242
|
+
} | {
|
|
243
|
+
All: {};
|
|
244
|
+
};
|
|
245
|
+
authorized_tokens: {
|
|
246
|
+
Specific: {};
|
|
247
|
+
} | {
|
|
248
|
+
All: {};
|
|
249
|
+
};
|
|
250
|
+
expiration: BN;
|
|
251
|
+
extra: {
|
|
252
|
+
0?: unknown;
|
|
253
|
+
};
|
|
254
|
+
major: number;
|
|
255
|
+
minor: number;
|
|
256
|
+
user: PublicKey;
|
|
257
|
+
};
|
|
258
|
+
}>;
|
|
259
|
+
export declare enum AuthorizedProgramsType {
|
|
260
|
+
All = 0,
|
|
261
|
+
Specific = 1
|
|
262
|
+
}
|
|
263
|
+
export declare enum AuthorizedTokens {
|
|
264
|
+
All = 0,
|
|
265
|
+
Specific = 1
|
|
266
|
+
}
|
|
23
267
|
export declare const getDomainRecordAddress: (domain: string) => PublicKey;
|
|
24
268
|
export declare enum SessionResultType {
|
|
25
269
|
Success = 0,
|
|
@@ -44,4 +288,5 @@ export type Session = {
|
|
|
44
288
|
walletPublicKey: PublicKey;
|
|
45
289
|
payer: PublicKey;
|
|
46
290
|
sendTransaction: (instructions: Parameters<SessionAdapter["sendTransaction"]>[1]) => Promise<TransactionResult>;
|
|
291
|
+
sessionInfo: z.infer<typeof sessionInfoSchema>;
|
|
47
292
|
};
|
package/cjs/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SessionResultType = exports.getDomainRecordAddress = exports.reestablishSession = exports.replaceSession = exports.establishSession = exports.createSolanaWalletAdapter = exports.TransactionResultType = void 0;
|
|
6
|
+
exports.SessionResultType = exports.getDomainRecordAddress = exports.AuthorizedTokens = exports.AuthorizedProgramsType = exports.getSessionAccount = exports.reestablishSession = exports.replaceSession = exports.establishSession = exports.createSolanaWalletAdapter = exports.TransactionResultType = void 0;
|
|
4
7
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
5
8
|
const sessions_idls_1 = require("@fogo/sessions-idls");
|
|
6
9
|
const mpl_token_metadata_1 = require("@metaplex-foundation/mpl-token-metadata");
|
|
@@ -10,6 +13,8 @@ const sha2_1 = require("@noble/hashes/sha2");
|
|
|
10
13
|
const kit_1 = require("@solana/kit");
|
|
11
14
|
const spl_token_1 = require("@solana/spl-token");
|
|
12
15
|
const web3_js_1 = require("@solana/web3.js");
|
|
16
|
+
const bn_js_1 = __importDefault(require("bn.js"));
|
|
17
|
+
const zod_1 = require("zod");
|
|
13
18
|
const adapter_js_1 = require("./adapter.js");
|
|
14
19
|
var adapter_js_2 = require("./adapter.js");
|
|
15
20
|
Object.defineProperty(exports, "TransactionResultType", { enumerable: true, get: function () { return adapter_js_2.TransactionResultType; } });
|
|
@@ -17,45 +22,139 @@ Object.defineProperty(exports, "createSolanaWalletAdapter", { enumerable: true,
|
|
|
17
22
|
const MESSAGE_HEADER = `Fogo Sessions:
|
|
18
23
|
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
24
|
`;
|
|
25
|
+
const UNLIMITED_TOKEN_PERMISSIONS_VALUE = "this app may spend any amount of any token";
|
|
26
|
+
const TOKENLESS_PERMISSIONS_VALUE = "this app may not spend any tokens";
|
|
20
27
|
const CURRENT_MAJOR = "0";
|
|
21
28
|
const CURRENT_MINOR = "1";
|
|
22
29
|
const establishSession = async (options) => {
|
|
23
30
|
const sessionKey = await (0, kit_1.generateKeyPair)();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
if (options.unlimited) {
|
|
32
|
+
return sendSessionEstablishTransaction(options, sessionKey, await Promise.all([
|
|
33
|
+
buildIntentInstruction(options, sessionKey),
|
|
34
|
+
buildStartSessionInstruction(options, sessionKey),
|
|
35
|
+
]));
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const filteredLimits = new Map(options.limits?.entries().filter(([, amount]) => amount > 0n));
|
|
39
|
+
const tokenInfo = filteredLimits.size > 0
|
|
40
|
+
? await getTokenInfo(options.adapter, filteredLimits)
|
|
41
|
+
: [];
|
|
42
|
+
const [intentInstruction, startSessionInstruction] = await Promise.all([
|
|
43
|
+
buildIntentInstruction(options, sessionKey, tokenInfo),
|
|
44
|
+
buildStartSessionInstruction(options, sessionKey, tokenInfo),
|
|
45
|
+
]);
|
|
46
|
+
return sendSessionEstablishTransaction(options, sessionKey, [
|
|
47
|
+
...buildCreateAssociatedTokenAccountInstructions(options, tokenInfo),
|
|
48
|
+
intentInstruction,
|
|
49
|
+
startSessionInstruction,
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
exports.establishSession = establishSession;
|
|
54
|
+
const sendSessionEstablishTransaction = async (options, sessionKey, instructions) => {
|
|
55
|
+
const result = await options.adapter.sendTransaction(sessionKey, instructions);
|
|
34
56
|
switch (result.type) {
|
|
35
57
|
case adapter_js_1.TransactionResultType.Success: {
|
|
36
|
-
|
|
58
|
+
const session = await createSession(options.adapter, options.walletPublicKey, sessionKey);
|
|
59
|
+
return session
|
|
60
|
+
? EstablishSessionResult.Success(result.signature, session)
|
|
61
|
+
: EstablishSessionResult.Failed(result.signature, new Error("Transaction succeeded, but the session was not created"));
|
|
37
62
|
}
|
|
38
63
|
case adapter_js_1.TransactionResultType.Failed: {
|
|
39
64
|
return EstablishSessionResult.Failed(result.signature, result.error);
|
|
40
65
|
}
|
|
41
66
|
}
|
|
42
67
|
};
|
|
43
|
-
exports.establishSession = establishSession;
|
|
44
68
|
const replaceSession = async (options) => (0, exports.establishSession)({
|
|
45
69
|
...options,
|
|
46
70
|
walletPublicKey: options.session.walletPublicKey,
|
|
47
71
|
});
|
|
48
72
|
exports.replaceSession = replaceSession;
|
|
49
|
-
// TODO we really should check to ensure the session is still valid...
|
|
50
73
|
const reestablishSession = async (adapter, walletPublicKey, sessionKey) => createSession(adapter, walletPublicKey, sessionKey);
|
|
51
74
|
exports.reestablishSession = reestablishSession;
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
75
|
+
const getSessionAccount = async (connection, sessionPublicKey) => {
|
|
76
|
+
const result = await connection.getAccountInfo(sessionPublicKey);
|
|
77
|
+
return result === null
|
|
78
|
+
? undefined
|
|
79
|
+
: sessionInfoSchema.parse(new anchor_1.BorshAccountsCoder(sessions_idls_1.SessionManagerIdl).decode("Session", result.data));
|
|
80
|
+
};
|
|
81
|
+
exports.getSessionAccount = getSessionAccount;
|
|
82
|
+
const createSession = async (adapter, walletPublicKey, sessionKey) => {
|
|
83
|
+
const sessionPublicKey = new web3_js_1.PublicKey(await (0, kit_1.getAddressFromPublicKey)(sessionKey.publicKey));
|
|
84
|
+
const sessionInfo = await (0, exports.getSessionAccount)(adapter.connection, sessionPublicKey);
|
|
85
|
+
return sessionInfo === undefined
|
|
86
|
+
? undefined
|
|
87
|
+
: {
|
|
88
|
+
sessionPublicKey,
|
|
89
|
+
walletPublicKey,
|
|
90
|
+
sessionKey,
|
|
91
|
+
payer: adapter.payer,
|
|
92
|
+
sendTransaction: (instructions) => adapter.sendTransaction(sessionKey, instructions),
|
|
93
|
+
sessionInfo,
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
const sessionInfoSchema = zod_1.z
|
|
97
|
+
.object({
|
|
98
|
+
session_info: zod_1.z.object({
|
|
99
|
+
authorized_programs: zod_1.z.union([
|
|
100
|
+
zod_1.z.object({
|
|
101
|
+
Specific: zod_1.z.object({
|
|
102
|
+
0: zod_1.z.array(zod_1.z.object({
|
|
103
|
+
program_id: zod_1.z.instanceof(web3_js_1.PublicKey),
|
|
104
|
+
signer_pda: zod_1.z.instanceof(web3_js_1.PublicKey),
|
|
105
|
+
})),
|
|
106
|
+
}),
|
|
107
|
+
}),
|
|
108
|
+
zod_1.z.object({
|
|
109
|
+
All: zod_1.z.object({}),
|
|
110
|
+
}),
|
|
111
|
+
]),
|
|
112
|
+
authorized_tokens: zod_1.z.union([
|
|
113
|
+
zod_1.z.object({ Specific: zod_1.z.object({}) }),
|
|
114
|
+
zod_1.z.object({ All: zod_1.z.object({}) }),
|
|
115
|
+
]),
|
|
116
|
+
expiration: zod_1.z.instanceof(bn_js_1.default),
|
|
117
|
+
extra: zod_1.z.object({
|
|
118
|
+
0: zod_1.z.unknown(),
|
|
119
|
+
}),
|
|
120
|
+
major: zod_1.z.number(),
|
|
121
|
+
minor: zod_1.z.number(),
|
|
122
|
+
user: zod_1.z.instanceof(web3_js_1.PublicKey),
|
|
123
|
+
}),
|
|
124
|
+
})
|
|
125
|
+
.transform(({ session_info }) => ({
|
|
126
|
+
authorizedPrograms: "All" in session_info.authorized_programs
|
|
127
|
+
? AuthorizedPrograms.All()
|
|
128
|
+
: AuthorizedPrograms.Specific(session_info.authorized_programs.Specific[0].map(({ program_id, signer_pda }) => ({
|
|
129
|
+
programId: program_id,
|
|
130
|
+
signerPda: signer_pda,
|
|
131
|
+
}))),
|
|
132
|
+
authorizedTokens: "All" in session_info.authorized_tokens
|
|
133
|
+
? AuthorizedTokens.All
|
|
134
|
+
: AuthorizedTokens.Specific,
|
|
135
|
+
expiration: new Date(Number(session_info.expiration) * 1000),
|
|
136
|
+
extra: session_info.extra[0],
|
|
137
|
+
major: session_info.major,
|
|
138
|
+
minor: session_info.minor,
|
|
139
|
+
user: session_info.user,
|
|
140
|
+
}));
|
|
141
|
+
var AuthorizedProgramsType;
|
|
142
|
+
(function (AuthorizedProgramsType) {
|
|
143
|
+
AuthorizedProgramsType[AuthorizedProgramsType["All"] = 0] = "All";
|
|
144
|
+
AuthorizedProgramsType[AuthorizedProgramsType["Specific"] = 1] = "Specific";
|
|
145
|
+
})(AuthorizedProgramsType || (exports.AuthorizedProgramsType = AuthorizedProgramsType = {}));
|
|
146
|
+
const AuthorizedPrograms = {
|
|
147
|
+
All: () => ({ type: AuthorizedProgramsType.All }),
|
|
148
|
+
Specific: (programs) => ({
|
|
149
|
+
type: AuthorizedProgramsType.Specific,
|
|
150
|
+
programs,
|
|
151
|
+
}),
|
|
152
|
+
};
|
|
153
|
+
var AuthorizedTokens;
|
|
154
|
+
(function (AuthorizedTokens) {
|
|
155
|
+
AuthorizedTokens[AuthorizedTokens["All"] = 0] = "All";
|
|
156
|
+
AuthorizedTokens[AuthorizedTokens["Specific"] = 1] = "Specific";
|
|
157
|
+
})(AuthorizedTokens || (exports.AuthorizedTokens = AuthorizedTokens = {}));
|
|
59
158
|
const SymbolOrMintType = {
|
|
60
159
|
Symbol: "Symbol",
|
|
61
160
|
Mint: "Mint",
|
|
@@ -70,13 +169,13 @@ const SymbolOrMint = {
|
|
|
70
169
|
mint,
|
|
71
170
|
}),
|
|
72
171
|
};
|
|
73
|
-
const getTokenInfo = async (
|
|
74
|
-
const umi = (0, umi_bundle_defaults_1.createUmi)(
|
|
75
|
-
return Promise.all(
|
|
172
|
+
const getTokenInfo = async (adapter, limits) => {
|
|
173
|
+
const umi = (0, umi_bundle_defaults_1.createUmi)(adapter.connection.rpcEndpoint);
|
|
174
|
+
return Promise.all(limits.entries().map(async ([mint, amount]) => {
|
|
76
175
|
const metaplexMint = (0, umi_1.publicKey)(mint.toBase58());
|
|
77
176
|
const metadataAddress = (0, mpl_token_metadata_1.findMetadataPda)(umi, { mint: metaplexMint })[0];
|
|
78
177
|
const [mintInfo, metadata] = await Promise.all([
|
|
79
|
-
(0, spl_token_1.getMint)(
|
|
178
|
+
(0, spl_token_1.getMint)(adapter.connection, mint),
|
|
80
179
|
(0, mpl_token_metadata_1.safeFetchMetadata)(umi, metadataAddress),
|
|
81
180
|
]);
|
|
82
181
|
return {
|
|
@@ -121,14 +220,21 @@ const buildMessage = async (body) => new TextEncoder().encode([
|
|
|
121
220
|
const serializeKV = (data) => Object.entries(data)
|
|
122
221
|
.map(([key, value]) => [key, ":", value.startsWith("\n") ? "" : " ", value].join(""))
|
|
123
222
|
.join("\n");
|
|
124
|
-
const serializeTokenList = (tokens) =>
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
223
|
+
const serializeTokenList = (tokens) => {
|
|
224
|
+
if (tokens === undefined) {
|
|
225
|
+
return UNLIMITED_TOKEN_PERMISSIONS_VALUE;
|
|
226
|
+
}
|
|
227
|
+
else if (tokens.length === 0) {
|
|
228
|
+
return TOKENLESS_PERMISSIONS_VALUE;
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
return tokens
|
|
232
|
+
.values()
|
|
233
|
+
.map(({ symbolOrMint, amount, decimals }) => `\n-${symbolOrMint.type === SymbolOrMintType.Symbol ? symbolOrMint.symbol : symbolOrMint.mint.toBase58()}: ${amountToString(amount, decimals)}`)
|
|
234
|
+
.toArray()
|
|
235
|
+
.join("");
|
|
236
|
+
}
|
|
237
|
+
};
|
|
132
238
|
const amountToString = (amount, decimals) => {
|
|
133
239
|
const asStr = amount.toString();
|
|
134
240
|
const whole = asStr.length > decimals ? asStr.slice(0, asStr.length - decimals) : "0";
|
|
@@ -146,35 +252,40 @@ const getDomainRecordAddress = (domain) => {
|
|
|
146
252
|
return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("domain-record"), hash], new web3_js_1.PublicKey(sessions_idls_1.DomainRegistryIdl.address))[0];
|
|
147
253
|
};
|
|
148
254
|
exports.getDomainRecordAddress = getDomainRecordAddress;
|
|
149
|
-
const buildStartSessionInstruction = async (options, sessionKey, tokens) =>
|
|
150
|
-
.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
},
|
|
167
|
-
...(symbolOrMint.type === SymbolOrMintType.Symbol
|
|
168
|
-
? [
|
|
255
|
+
const buildStartSessionInstruction = async (options, sessionKey, tokens) => {
|
|
256
|
+
const instruction = new sessions_idls_1.SessionManagerProgram(new anchor_1.AnchorProvider(options.adapter.connection, {}, {})).methods
|
|
257
|
+
.startSession()
|
|
258
|
+
.accounts({
|
|
259
|
+
sponsor: options.adapter.payer,
|
|
260
|
+
session: await (0, kit_1.getAddressFromPublicKey)(sessionKey.publicKey),
|
|
261
|
+
domainRegistry: (0, exports.getDomainRecordAddress)(options.adapter.domain),
|
|
262
|
+
});
|
|
263
|
+
return tokens === undefined
|
|
264
|
+
? instruction.instruction()
|
|
265
|
+
: instruction
|
|
266
|
+
.remainingAccounts(tokens.flatMap(({ symbolOrMint, mint, metadataAddress }) => [
|
|
267
|
+
{
|
|
268
|
+
pubkey: (0, spl_token_1.getAssociatedTokenAddressSync)(mint, options.walletPublicKey),
|
|
269
|
+
isWritable: true,
|
|
270
|
+
isSigner: false,
|
|
271
|
+
},
|
|
169
272
|
{
|
|
170
|
-
pubkey:
|
|
273
|
+
pubkey: mint,
|
|
171
274
|
isWritable: false,
|
|
172
275
|
isSigner: false,
|
|
173
276
|
},
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
277
|
+
...(symbolOrMint.type === SymbolOrMintType.Symbol
|
|
278
|
+
? [
|
|
279
|
+
{
|
|
280
|
+
pubkey: metadataAddress,
|
|
281
|
+
isWritable: false,
|
|
282
|
+
isSigner: false,
|
|
283
|
+
},
|
|
284
|
+
]
|
|
285
|
+
: []),
|
|
286
|
+
]))
|
|
287
|
+
.instruction();
|
|
288
|
+
};
|
|
178
289
|
var SessionResultType;
|
|
179
290
|
(function (SessionResultType) {
|
|
180
291
|
SessionResultType[SessionResultType["Success"] = 0] = "Success";
|
package/cjs/paymaster.js
CHANGED
|
@@ -4,16 +4,12 @@ exports.createPaymasterEndpoint = exports.sponsorAndSend = void 0;
|
|
|
4
4
|
const compat_1 = require("@solana/compat");
|
|
5
5
|
const kit_1 = require("@solana/kit");
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
|
-
const sponsorAndSend = async (rpc, sponsor, transaction) =>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
})
|
|
14
|
-
.send();
|
|
15
|
-
return (0, kit_1.getSignatureFromTransaction)(signedTransaction);
|
|
16
|
-
};
|
|
7
|
+
const sponsorAndSend = async (rpc, sponsor, transaction) => rpc
|
|
8
|
+
.sendTransaction((0, kit_1.getBase64EncodedWireTransaction)(await (0, kit_1.signTransaction)([sponsor], transaction)), {
|
|
9
|
+
encoding: "base64",
|
|
10
|
+
skipPreflight: true,
|
|
11
|
+
})
|
|
12
|
+
.send();
|
|
17
13
|
exports.sponsorAndSend = sponsorAndSend;
|
|
18
14
|
const createPaymasterEndpoint = async (options) => {
|
|
19
15
|
const rpc = (0, kit_1.createSolanaRpc)(options.rpc);
|
package/esm/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import type { TransactionError } from "@solana/web3.js";
|
|
1
|
+
import type { TransactionError, Connection } from "@solana/web3.js";
|
|
2
2
|
import { PublicKey } from "@solana/web3.js";
|
|
3
|
+
import BN from "bn.js";
|
|
4
|
+
import { z } from "zod";
|
|
3
5
|
import type { SessionAdapter, TransactionResult } from "./adapter.js";
|
|
4
6
|
export { type SessionAdapter, type TransactionResult, TransactionResultType, createSolanaWalletAdapter, } from "./adapter.js";
|
|
5
7
|
type EstablishSessionOptions = {
|
|
@@ -7,19 +9,261 @@ type EstablishSessionOptions = {
|
|
|
7
9
|
walletPublicKey: PublicKey;
|
|
8
10
|
signMessage: (message: Uint8Array) => Promise<Uint8Array>;
|
|
9
11
|
expires: Date;
|
|
10
|
-
limits: Map<PublicKey, bigint>;
|
|
11
12
|
extra?: string | undefined;
|
|
12
|
-
}
|
|
13
|
+
} & ({
|
|
14
|
+
limits?: Map<PublicKey, bigint>;
|
|
15
|
+
unlimited?: false;
|
|
16
|
+
} | {
|
|
17
|
+
unlimited: true;
|
|
18
|
+
});
|
|
13
19
|
export declare const establishSession: (options: EstablishSessionOptions) => Promise<EstablishSessionResult>;
|
|
14
20
|
export declare const replaceSession: (options: {
|
|
15
21
|
adapter: SessionAdapter;
|
|
16
22
|
session: Session;
|
|
17
23
|
signMessage: (message: Uint8Array) => Promise<Uint8Array>;
|
|
18
24
|
expires: Date;
|
|
19
|
-
limits: Map<PublicKey, bigint>;
|
|
20
25
|
extra?: string | undefined;
|
|
21
|
-
}
|
|
22
|
-
|
|
26
|
+
} & ({
|
|
27
|
+
limits?: Map<PublicKey, bigint>;
|
|
28
|
+
unlimited?: false;
|
|
29
|
+
} | {
|
|
30
|
+
unlimited: true;
|
|
31
|
+
})) => Promise<EstablishSessionResult>;
|
|
32
|
+
export declare const reestablishSession: (adapter: SessionAdapter, walletPublicKey: PublicKey, sessionKey: CryptoKeyPair) => Promise<Session | undefined>;
|
|
33
|
+
export declare const getSessionAccount: (connection: Connection, sessionPublicKey: PublicKey) => Promise<{
|
|
34
|
+
authorizedPrograms: {
|
|
35
|
+
type: AuthorizedProgramsType.All;
|
|
36
|
+
} | {
|
|
37
|
+
type: AuthorizedProgramsType.Specific;
|
|
38
|
+
programs: {
|
|
39
|
+
programId: PublicKey;
|
|
40
|
+
signerPda: PublicKey;
|
|
41
|
+
}[];
|
|
42
|
+
};
|
|
43
|
+
authorizedTokens: AuthorizedTokens;
|
|
44
|
+
expiration: Date;
|
|
45
|
+
extra: unknown;
|
|
46
|
+
major: number;
|
|
47
|
+
minor: number;
|
|
48
|
+
user: PublicKey;
|
|
49
|
+
} | undefined>;
|
|
50
|
+
declare const sessionInfoSchema: z.ZodEffects<z.ZodObject<{
|
|
51
|
+
session_info: z.ZodObject<{
|
|
52
|
+
authorized_programs: z.ZodUnion<[z.ZodObject<{
|
|
53
|
+
Specific: z.ZodObject<{
|
|
54
|
+
0: z.ZodArray<z.ZodObject<{
|
|
55
|
+
program_id: z.ZodType<PublicKey, z.ZodTypeDef, PublicKey>;
|
|
56
|
+
signer_pda: z.ZodType<PublicKey, z.ZodTypeDef, PublicKey>;
|
|
57
|
+
}, "strip", z.ZodTypeAny, {
|
|
58
|
+
program_id: PublicKey;
|
|
59
|
+
signer_pda: PublicKey;
|
|
60
|
+
}, {
|
|
61
|
+
program_id: PublicKey;
|
|
62
|
+
signer_pda: PublicKey;
|
|
63
|
+
}>, "many">;
|
|
64
|
+
}, "strip", z.ZodTypeAny, {
|
|
65
|
+
0: {
|
|
66
|
+
program_id: PublicKey;
|
|
67
|
+
signer_pda: PublicKey;
|
|
68
|
+
}[];
|
|
69
|
+
}, {
|
|
70
|
+
0: {
|
|
71
|
+
program_id: PublicKey;
|
|
72
|
+
signer_pda: PublicKey;
|
|
73
|
+
}[];
|
|
74
|
+
}>;
|
|
75
|
+
}, "strip", z.ZodTypeAny, {
|
|
76
|
+
Specific: {
|
|
77
|
+
0: {
|
|
78
|
+
program_id: PublicKey;
|
|
79
|
+
signer_pda: PublicKey;
|
|
80
|
+
}[];
|
|
81
|
+
};
|
|
82
|
+
}, {
|
|
83
|
+
Specific: {
|
|
84
|
+
0: {
|
|
85
|
+
program_id: PublicKey;
|
|
86
|
+
signer_pda: PublicKey;
|
|
87
|
+
}[];
|
|
88
|
+
};
|
|
89
|
+
}>, z.ZodObject<{
|
|
90
|
+
All: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
|
|
91
|
+
}, "strip", z.ZodTypeAny, {
|
|
92
|
+
All: {};
|
|
93
|
+
}, {
|
|
94
|
+
All: {};
|
|
95
|
+
}>]>;
|
|
96
|
+
authorized_tokens: z.ZodUnion<[z.ZodObject<{
|
|
97
|
+
Specific: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
|
|
98
|
+
}, "strip", z.ZodTypeAny, {
|
|
99
|
+
Specific: {};
|
|
100
|
+
}, {
|
|
101
|
+
Specific: {};
|
|
102
|
+
}>, z.ZodObject<{
|
|
103
|
+
All: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
|
|
104
|
+
}, "strip", z.ZodTypeAny, {
|
|
105
|
+
All: {};
|
|
106
|
+
}, {
|
|
107
|
+
All: {};
|
|
108
|
+
}>]>;
|
|
109
|
+
expiration: z.ZodType<BN, z.ZodTypeDef, BN>;
|
|
110
|
+
extra: z.ZodObject<{
|
|
111
|
+
0: z.ZodUnknown;
|
|
112
|
+
}, "strip", z.ZodTypeAny, {
|
|
113
|
+
0?: unknown;
|
|
114
|
+
}, {
|
|
115
|
+
0?: unknown;
|
|
116
|
+
}>;
|
|
117
|
+
major: z.ZodNumber;
|
|
118
|
+
minor: z.ZodNumber;
|
|
119
|
+
user: z.ZodType<PublicKey, z.ZodTypeDef, PublicKey>;
|
|
120
|
+
}, "strip", z.ZodTypeAny, {
|
|
121
|
+
authorized_programs: {
|
|
122
|
+
Specific: {
|
|
123
|
+
0: {
|
|
124
|
+
program_id: PublicKey;
|
|
125
|
+
signer_pda: PublicKey;
|
|
126
|
+
}[];
|
|
127
|
+
};
|
|
128
|
+
} | {
|
|
129
|
+
All: {};
|
|
130
|
+
};
|
|
131
|
+
authorized_tokens: {
|
|
132
|
+
Specific: {};
|
|
133
|
+
} | {
|
|
134
|
+
All: {};
|
|
135
|
+
};
|
|
136
|
+
expiration: BN;
|
|
137
|
+
extra: {
|
|
138
|
+
0?: unknown;
|
|
139
|
+
};
|
|
140
|
+
major: number;
|
|
141
|
+
minor: number;
|
|
142
|
+
user: PublicKey;
|
|
143
|
+
}, {
|
|
144
|
+
authorized_programs: {
|
|
145
|
+
Specific: {
|
|
146
|
+
0: {
|
|
147
|
+
program_id: PublicKey;
|
|
148
|
+
signer_pda: PublicKey;
|
|
149
|
+
}[];
|
|
150
|
+
};
|
|
151
|
+
} | {
|
|
152
|
+
All: {};
|
|
153
|
+
};
|
|
154
|
+
authorized_tokens: {
|
|
155
|
+
Specific: {};
|
|
156
|
+
} | {
|
|
157
|
+
All: {};
|
|
158
|
+
};
|
|
159
|
+
expiration: BN;
|
|
160
|
+
extra: {
|
|
161
|
+
0?: unknown;
|
|
162
|
+
};
|
|
163
|
+
major: number;
|
|
164
|
+
minor: number;
|
|
165
|
+
user: PublicKey;
|
|
166
|
+
}>;
|
|
167
|
+
}, "strip", z.ZodTypeAny, {
|
|
168
|
+
session_info: {
|
|
169
|
+
authorized_programs: {
|
|
170
|
+
Specific: {
|
|
171
|
+
0: {
|
|
172
|
+
program_id: PublicKey;
|
|
173
|
+
signer_pda: PublicKey;
|
|
174
|
+
}[];
|
|
175
|
+
};
|
|
176
|
+
} | {
|
|
177
|
+
All: {};
|
|
178
|
+
};
|
|
179
|
+
authorized_tokens: {
|
|
180
|
+
Specific: {};
|
|
181
|
+
} | {
|
|
182
|
+
All: {};
|
|
183
|
+
};
|
|
184
|
+
expiration: BN;
|
|
185
|
+
extra: {
|
|
186
|
+
0?: unknown;
|
|
187
|
+
};
|
|
188
|
+
major: number;
|
|
189
|
+
minor: number;
|
|
190
|
+
user: PublicKey;
|
|
191
|
+
};
|
|
192
|
+
}, {
|
|
193
|
+
session_info: {
|
|
194
|
+
authorized_programs: {
|
|
195
|
+
Specific: {
|
|
196
|
+
0: {
|
|
197
|
+
program_id: PublicKey;
|
|
198
|
+
signer_pda: PublicKey;
|
|
199
|
+
}[];
|
|
200
|
+
};
|
|
201
|
+
} | {
|
|
202
|
+
All: {};
|
|
203
|
+
};
|
|
204
|
+
authorized_tokens: {
|
|
205
|
+
Specific: {};
|
|
206
|
+
} | {
|
|
207
|
+
All: {};
|
|
208
|
+
};
|
|
209
|
+
expiration: BN;
|
|
210
|
+
extra: {
|
|
211
|
+
0?: unknown;
|
|
212
|
+
};
|
|
213
|
+
major: number;
|
|
214
|
+
minor: number;
|
|
215
|
+
user: PublicKey;
|
|
216
|
+
};
|
|
217
|
+
}>, {
|
|
218
|
+
authorizedPrograms: {
|
|
219
|
+
type: AuthorizedProgramsType.All;
|
|
220
|
+
} | {
|
|
221
|
+
type: AuthorizedProgramsType.Specific;
|
|
222
|
+
programs: {
|
|
223
|
+
programId: PublicKey;
|
|
224
|
+
signerPda: PublicKey;
|
|
225
|
+
}[];
|
|
226
|
+
};
|
|
227
|
+
authorizedTokens: AuthorizedTokens;
|
|
228
|
+
expiration: Date;
|
|
229
|
+
extra: unknown;
|
|
230
|
+
major: number;
|
|
231
|
+
minor: number;
|
|
232
|
+
user: PublicKey;
|
|
233
|
+
}, {
|
|
234
|
+
session_info: {
|
|
235
|
+
authorized_programs: {
|
|
236
|
+
Specific: {
|
|
237
|
+
0: {
|
|
238
|
+
program_id: PublicKey;
|
|
239
|
+
signer_pda: PublicKey;
|
|
240
|
+
}[];
|
|
241
|
+
};
|
|
242
|
+
} | {
|
|
243
|
+
All: {};
|
|
244
|
+
};
|
|
245
|
+
authorized_tokens: {
|
|
246
|
+
Specific: {};
|
|
247
|
+
} | {
|
|
248
|
+
All: {};
|
|
249
|
+
};
|
|
250
|
+
expiration: BN;
|
|
251
|
+
extra: {
|
|
252
|
+
0?: unknown;
|
|
253
|
+
};
|
|
254
|
+
major: number;
|
|
255
|
+
minor: number;
|
|
256
|
+
user: PublicKey;
|
|
257
|
+
};
|
|
258
|
+
}>;
|
|
259
|
+
export declare enum AuthorizedProgramsType {
|
|
260
|
+
All = 0,
|
|
261
|
+
Specific = 1
|
|
262
|
+
}
|
|
263
|
+
export declare enum AuthorizedTokens {
|
|
264
|
+
All = 0,
|
|
265
|
+
Specific = 1
|
|
266
|
+
}
|
|
23
267
|
export declare const getDomainRecordAddress: (domain: string) => PublicKey;
|
|
24
268
|
export declare enum SessionResultType {
|
|
25
269
|
Success = 0,
|
|
@@ -44,4 +288,5 @@ export type Session = {
|
|
|
44
288
|
walletPublicKey: PublicKey;
|
|
45
289
|
payer: PublicKey;
|
|
46
290
|
sendTransaction: (instructions: Parameters<SessionAdapter["sendTransaction"]>[1]) => Promise<TransactionResult>;
|
|
291
|
+
sessionInfo: z.infer<typeof sessionInfoSchema>;
|
|
47
292
|
};
|
package/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AnchorProvider } from "@coral-xyz/anchor";
|
|
2
|
-
import { DomainRegistryIdl, SessionManagerProgram } from "@fogo/sessions-idls";
|
|
1
|
+
import { AnchorProvider, BorshAccountsCoder } from "@coral-xyz/anchor";
|
|
2
|
+
import { DomainRegistryIdl, SessionManagerProgram, SessionManagerIdl, } from "@fogo/sessions-idls";
|
|
3
3
|
import { findMetadataPda, safeFetchMetadata, } from "@metaplex-foundation/mpl-token-metadata";
|
|
4
4
|
import { publicKey as metaplexPublicKey } from "@metaplex-foundation/umi";
|
|
5
5
|
import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
|
|
@@ -7,28 +7,49 @@ import { sha256 } from "@noble/hashes/sha2";
|
|
|
7
7
|
import { generateKeyPair, getAddressFromPublicKey } from "@solana/kit";
|
|
8
8
|
import { createAssociatedTokenAccountIdempotentInstruction, getAssociatedTokenAddressSync, getMint, } from "@solana/spl-token";
|
|
9
9
|
import { Ed25519Program, PublicKey } from "@solana/web3.js";
|
|
10
|
+
import BN from "bn.js";
|
|
11
|
+
import { z } from "zod";
|
|
10
12
|
import { TransactionResultType } from "./adapter.js";
|
|
11
13
|
export { TransactionResultType, createSolanaWalletAdapter, } from "./adapter.js";
|
|
12
14
|
const MESSAGE_HEADER = `Fogo Sessions:
|
|
13
15
|
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.
|
|
14
16
|
`;
|
|
17
|
+
const UNLIMITED_TOKEN_PERMISSIONS_VALUE = "this app may spend any amount of any token";
|
|
18
|
+
const TOKENLESS_PERMISSIONS_VALUE = "this app may not spend any tokens";
|
|
15
19
|
const CURRENT_MAJOR = "0";
|
|
16
20
|
const CURRENT_MINOR = "1";
|
|
17
21
|
export const establishSession = async (options) => {
|
|
18
22
|
const sessionKey = await generateKeyPair();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
if (options.unlimited) {
|
|
24
|
+
return sendSessionEstablishTransaction(options, sessionKey, await Promise.all([
|
|
25
|
+
buildIntentInstruction(options, sessionKey),
|
|
26
|
+
buildStartSessionInstruction(options, sessionKey),
|
|
27
|
+
]));
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const filteredLimits = new Map(options.limits?.entries().filter(([, amount]) => amount > 0n));
|
|
31
|
+
const tokenInfo = filteredLimits.size > 0
|
|
32
|
+
? await getTokenInfo(options.adapter, filteredLimits)
|
|
33
|
+
: [];
|
|
34
|
+
const [intentInstruction, startSessionInstruction] = await Promise.all([
|
|
35
|
+
buildIntentInstruction(options, sessionKey, tokenInfo),
|
|
36
|
+
buildStartSessionInstruction(options, sessionKey, tokenInfo),
|
|
37
|
+
]);
|
|
38
|
+
return sendSessionEstablishTransaction(options, sessionKey, [
|
|
39
|
+
...buildCreateAssociatedTokenAccountInstructions(options, tokenInfo),
|
|
40
|
+
intentInstruction,
|
|
41
|
+
startSessionInstruction,
|
|
42
|
+
]);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const sendSessionEstablishTransaction = async (options, sessionKey, instructions) => {
|
|
46
|
+
const result = await options.adapter.sendTransaction(sessionKey, instructions);
|
|
29
47
|
switch (result.type) {
|
|
30
48
|
case TransactionResultType.Success: {
|
|
31
|
-
|
|
49
|
+
const session = await createSession(options.adapter, options.walletPublicKey, sessionKey);
|
|
50
|
+
return session
|
|
51
|
+
? EstablishSessionResult.Success(result.signature, session)
|
|
52
|
+
: EstablishSessionResult.Failed(result.signature, new Error("Transaction succeeded, but the session was not created"));
|
|
32
53
|
}
|
|
33
54
|
case TransactionResultType.Failed: {
|
|
34
55
|
return EstablishSessionResult.Failed(result.signature, result.error);
|
|
@@ -39,15 +60,89 @@ export const replaceSession = async (options) => establishSession({
|
|
|
39
60
|
...options,
|
|
40
61
|
walletPublicKey: options.session.walletPublicKey,
|
|
41
62
|
});
|
|
42
|
-
// TODO we really should check to ensure the session is still valid...
|
|
43
63
|
export const reestablishSession = async (adapter, walletPublicKey, sessionKey) => createSession(adapter, walletPublicKey, sessionKey);
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
64
|
+
export const getSessionAccount = async (connection, sessionPublicKey) => {
|
|
65
|
+
const result = await connection.getAccountInfo(sessionPublicKey);
|
|
66
|
+
return result === null
|
|
67
|
+
? undefined
|
|
68
|
+
: sessionInfoSchema.parse(new BorshAccountsCoder(SessionManagerIdl).decode("Session", result.data));
|
|
69
|
+
};
|
|
70
|
+
const createSession = async (adapter, walletPublicKey, sessionKey) => {
|
|
71
|
+
const sessionPublicKey = new PublicKey(await getAddressFromPublicKey(sessionKey.publicKey));
|
|
72
|
+
const sessionInfo = await getSessionAccount(adapter.connection, sessionPublicKey);
|
|
73
|
+
return sessionInfo === undefined
|
|
74
|
+
? undefined
|
|
75
|
+
: {
|
|
76
|
+
sessionPublicKey,
|
|
77
|
+
walletPublicKey,
|
|
78
|
+
sessionKey,
|
|
79
|
+
payer: adapter.payer,
|
|
80
|
+
sendTransaction: (instructions) => adapter.sendTransaction(sessionKey, instructions),
|
|
81
|
+
sessionInfo,
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
const sessionInfoSchema = z
|
|
85
|
+
.object({
|
|
86
|
+
session_info: z.object({
|
|
87
|
+
authorized_programs: z.union([
|
|
88
|
+
z.object({
|
|
89
|
+
Specific: z.object({
|
|
90
|
+
0: z.array(z.object({
|
|
91
|
+
program_id: z.instanceof(PublicKey),
|
|
92
|
+
signer_pda: z.instanceof(PublicKey),
|
|
93
|
+
})),
|
|
94
|
+
}),
|
|
95
|
+
}),
|
|
96
|
+
z.object({
|
|
97
|
+
All: z.object({}),
|
|
98
|
+
}),
|
|
99
|
+
]),
|
|
100
|
+
authorized_tokens: z.union([
|
|
101
|
+
z.object({ Specific: z.object({}) }),
|
|
102
|
+
z.object({ All: z.object({}) }),
|
|
103
|
+
]),
|
|
104
|
+
expiration: z.instanceof(BN),
|
|
105
|
+
extra: z.object({
|
|
106
|
+
0: z.unknown(),
|
|
107
|
+
}),
|
|
108
|
+
major: z.number(),
|
|
109
|
+
minor: z.number(),
|
|
110
|
+
user: z.instanceof(PublicKey),
|
|
111
|
+
}),
|
|
112
|
+
})
|
|
113
|
+
.transform(({ session_info }) => ({
|
|
114
|
+
authorizedPrograms: "All" in session_info.authorized_programs
|
|
115
|
+
? AuthorizedPrograms.All()
|
|
116
|
+
: AuthorizedPrograms.Specific(session_info.authorized_programs.Specific[0].map(({ program_id, signer_pda }) => ({
|
|
117
|
+
programId: program_id,
|
|
118
|
+
signerPda: signer_pda,
|
|
119
|
+
}))),
|
|
120
|
+
authorizedTokens: "All" in session_info.authorized_tokens
|
|
121
|
+
? AuthorizedTokens.All
|
|
122
|
+
: AuthorizedTokens.Specific,
|
|
123
|
+
expiration: new Date(Number(session_info.expiration) * 1000),
|
|
124
|
+
extra: session_info.extra[0],
|
|
125
|
+
major: session_info.major,
|
|
126
|
+
minor: session_info.minor,
|
|
127
|
+
user: session_info.user,
|
|
128
|
+
}));
|
|
129
|
+
export var AuthorizedProgramsType;
|
|
130
|
+
(function (AuthorizedProgramsType) {
|
|
131
|
+
AuthorizedProgramsType[AuthorizedProgramsType["All"] = 0] = "All";
|
|
132
|
+
AuthorizedProgramsType[AuthorizedProgramsType["Specific"] = 1] = "Specific";
|
|
133
|
+
})(AuthorizedProgramsType || (AuthorizedProgramsType = {}));
|
|
134
|
+
const AuthorizedPrograms = {
|
|
135
|
+
All: () => ({ type: AuthorizedProgramsType.All }),
|
|
136
|
+
Specific: (programs) => ({
|
|
137
|
+
type: AuthorizedProgramsType.Specific,
|
|
138
|
+
programs,
|
|
139
|
+
}),
|
|
140
|
+
};
|
|
141
|
+
export var AuthorizedTokens;
|
|
142
|
+
(function (AuthorizedTokens) {
|
|
143
|
+
AuthorizedTokens[AuthorizedTokens["All"] = 0] = "All";
|
|
144
|
+
AuthorizedTokens[AuthorizedTokens["Specific"] = 1] = "Specific";
|
|
145
|
+
})(AuthorizedTokens || (AuthorizedTokens = {}));
|
|
51
146
|
const SymbolOrMintType = {
|
|
52
147
|
Symbol: "Symbol",
|
|
53
148
|
Mint: "Mint",
|
|
@@ -62,13 +157,13 @@ const SymbolOrMint = {
|
|
|
62
157
|
mint,
|
|
63
158
|
}),
|
|
64
159
|
};
|
|
65
|
-
const getTokenInfo = async (
|
|
66
|
-
const umi = createUmi(
|
|
67
|
-
return Promise.all(
|
|
160
|
+
const getTokenInfo = async (adapter, limits) => {
|
|
161
|
+
const umi = createUmi(adapter.connection.rpcEndpoint);
|
|
162
|
+
return Promise.all(limits.entries().map(async ([mint, amount]) => {
|
|
68
163
|
const metaplexMint = metaplexPublicKey(mint.toBase58());
|
|
69
164
|
const metadataAddress = findMetadataPda(umi, { mint: metaplexMint })[0];
|
|
70
165
|
const [mintInfo, metadata] = await Promise.all([
|
|
71
|
-
getMint(
|
|
166
|
+
getMint(adapter.connection, mint),
|
|
72
167
|
safeFetchMetadata(umi, metadataAddress),
|
|
73
168
|
]);
|
|
74
169
|
return {
|
|
@@ -113,14 +208,21 @@ const buildMessage = async (body) => new TextEncoder().encode([
|
|
|
113
208
|
const serializeKV = (data) => Object.entries(data)
|
|
114
209
|
.map(([key, value]) => [key, ":", value.startsWith("\n") ? "" : " ", value].join(""))
|
|
115
210
|
.join("\n");
|
|
116
|
-
const serializeTokenList = (tokens) =>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
211
|
+
const serializeTokenList = (tokens) => {
|
|
212
|
+
if (tokens === undefined) {
|
|
213
|
+
return UNLIMITED_TOKEN_PERMISSIONS_VALUE;
|
|
214
|
+
}
|
|
215
|
+
else if (tokens.length === 0) {
|
|
216
|
+
return TOKENLESS_PERMISSIONS_VALUE;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
return tokens
|
|
220
|
+
.values()
|
|
221
|
+
.map(({ symbolOrMint, amount, decimals }) => `\n-${symbolOrMint.type === SymbolOrMintType.Symbol ? symbolOrMint.symbol : symbolOrMint.mint.toBase58()}: ${amountToString(amount, decimals)}`)
|
|
222
|
+
.toArray()
|
|
223
|
+
.join("");
|
|
224
|
+
}
|
|
225
|
+
};
|
|
124
226
|
const amountToString = (amount, decimals) => {
|
|
125
227
|
const asStr = amount.toString();
|
|
126
228
|
const whole = asStr.length > decimals ? asStr.slice(0, asStr.length - decimals) : "0";
|
|
@@ -137,35 +239,40 @@ export const getDomainRecordAddress = (domain) => {
|
|
|
137
239
|
const hash = sha256(domain);
|
|
138
240
|
return PublicKey.findProgramAddressSync([Buffer.from("domain-record"), hash], new PublicKey(DomainRegistryIdl.address))[0];
|
|
139
241
|
};
|
|
140
|
-
const buildStartSessionInstruction = async (options, sessionKey, tokens) =>
|
|
141
|
-
.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
pubkey: mint,
|
|
155
|
-
isWritable: false,
|
|
156
|
-
isSigner: false,
|
|
157
|
-
},
|
|
158
|
-
...(symbolOrMint.type === SymbolOrMintType.Symbol
|
|
159
|
-
? [
|
|
242
|
+
const buildStartSessionInstruction = async (options, sessionKey, tokens) => {
|
|
243
|
+
const instruction = new SessionManagerProgram(new AnchorProvider(options.adapter.connection, {}, {})).methods
|
|
244
|
+
.startSession()
|
|
245
|
+
.accounts({
|
|
246
|
+
sponsor: options.adapter.payer,
|
|
247
|
+
session: await getAddressFromPublicKey(sessionKey.publicKey),
|
|
248
|
+
domainRegistry: getDomainRecordAddress(options.adapter.domain),
|
|
249
|
+
});
|
|
250
|
+
return tokens === undefined
|
|
251
|
+
? instruction.instruction()
|
|
252
|
+
: instruction
|
|
253
|
+
.remainingAccounts(tokens.flatMap(({ symbolOrMint, mint, metadataAddress }) => [
|
|
160
254
|
{
|
|
161
|
-
pubkey:
|
|
255
|
+
pubkey: getAssociatedTokenAddressSync(mint, options.walletPublicKey),
|
|
256
|
+
isWritable: true,
|
|
257
|
+
isSigner: false,
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
pubkey: mint,
|
|
162
261
|
isWritable: false,
|
|
163
262
|
isSigner: false,
|
|
164
263
|
},
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
264
|
+
...(symbolOrMint.type === SymbolOrMintType.Symbol
|
|
265
|
+
? [
|
|
266
|
+
{
|
|
267
|
+
pubkey: metadataAddress,
|
|
268
|
+
isWritable: false,
|
|
269
|
+
isSigner: false,
|
|
270
|
+
},
|
|
271
|
+
]
|
|
272
|
+
: []),
|
|
273
|
+
]))
|
|
274
|
+
.instruction();
|
|
275
|
+
};
|
|
169
276
|
export var SessionResultType;
|
|
170
277
|
(function (SessionResultType) {
|
|
171
278
|
SessionResultType[SessionResultType["Success"] = 0] = "Success";
|
package/esm/paymaster.js
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { fromLegacyKeypair } from "@solana/compat";
|
|
2
|
-
import { signTransaction, createSolanaRpc, getBase64EncodedWireTransaction, getTransactionDecoder, getBase64Encoder,
|
|
2
|
+
import { signTransaction, createSolanaRpc, getBase64EncodedWireTransaction, getTransactionDecoder, getBase64Encoder, } from "@solana/kit";
|
|
3
3
|
import { Keypair } from "@solana/web3.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
export const sponsorAndSend = async (rpc, sponsor, transaction) =>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
})
|
|
12
|
-
.send();
|
|
13
|
-
return getSignatureFromTransaction(signedTransaction);
|
|
14
|
-
};
|
|
5
|
+
export const sponsorAndSend = async (rpc, sponsor, transaction) => rpc
|
|
6
|
+
.sendTransaction(getBase64EncodedWireTransaction(await signTransaction([sponsor], transaction)), {
|
|
7
|
+
encoding: "base64",
|
|
8
|
+
skipPreflight: true,
|
|
9
|
+
})
|
|
10
|
+
.send();
|
|
15
11
|
export const createPaymasterEndpoint = async (options) => {
|
|
16
12
|
const rpc = createSolanaRpc(options.rpc);
|
|
17
13
|
const sponsor = await fromLegacyKeypair(options.sponsor);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fogo/sessions-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "A set of utilities for integrating with Fogo sessions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fogo",
|
|
@@ -45,8 +45,9 @@
|
|
|
45
45
|
"@solana/kit": "^2.1.1",
|
|
46
46
|
"@solana/spl-token": "^0.4.13",
|
|
47
47
|
"@solana/web3.js": "^1.92.3",
|
|
48
|
+
"bn.js": "^5.1.2",
|
|
48
49
|
"bs58": "^6.0.0",
|
|
49
50
|
"zod": "^3.25.62",
|
|
50
|
-
"@fogo/sessions-idls": "^0.0.
|
|
51
|
+
"@fogo/sessions-idls": "^0.0.3"
|
|
51
52
|
}
|
|
52
53
|
}
|