@loyal-labs/private-transactions 0.2.1 → 0.2.3

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @loyal-labs/private-transactions
2
2
 
3
- SDK for Telegram-based private SPL token deposits and transfers using MagicBlock Private Ephemeral Rollups (PER). This wraps the `telegram-private-transfer` Anchor program and provides helpers for permissions, delegation, private transfers, and undelegation.
3
+ SDK for private SPL token deposits and transfers using [MagicBlock Private Ephemeral Rollups (PER)](https://docs.magicblock.gg/pages/private-ephemeral-rollups-pers/introduction/authorization). This package wraps the `telegram-private-transfer` Anchor program and provides helpers for permissions, delegation, private transfers, claims, and undelegation.
4
4
 
5
5
  ## Installation
6
6
 
@@ -19,144 +19,162 @@ bun add @coral-xyz/anchor @solana/web3.js @solana/spl-token @magicblock-labs/eph
19
19
  ## Quick Start
20
20
 
21
21
  ```ts
22
- import { Connection, PublicKey } from "@solana/web3.js";
22
+ import { Keypair, PublicKey } from "@solana/web3.js";
23
23
  import {
24
+ ER_VALIDATOR,
24
25
  LoyalPrivateTransactionsClient,
25
26
  MAGIC_CONTEXT_ID,
26
27
  MAGIC_PROGRAM_ID,
27
28
  } from "@loyal-labs/private-transactions";
28
29
 
29
- const connection = new Connection("https://api.devnet.solana.com");
30
- const client = LoyalPrivateTransactionsClient.from(connection, myKeypair);
31
-
30
+ const signer = Keypair.fromSecretKey(Uint8Array.from([...secretBytes]));
32
31
  const tokenMint = new PublicKey("<mint>");
33
32
 
34
- // Initialize a user deposit
33
+ const client = await LoyalPrivateTransactionsClient.fromConfig({
34
+ signer,
35
+ baseRpcEndpoint: "https://api.devnet.solana.com",
36
+ // Mainnet: https://mainnet-tee.magicblock.app
37
+ // Devnet: https://tee.magicblock.app
38
+ ephemeralRpcEndpoint: "https://mainnet-tee.magicblock.app",
39
+ ephemeralWsEndpoint: "wss://mainnet-tee.magicblock.app",
40
+ commitment: "confirmed",
41
+ });
42
+
43
+ // Shield: move tokens into private deposit
35
44
  await client.initializeDeposit({
36
45
  tokenMint,
37
- user: myKeypair.publicKey,
38
- payer: myKeypair.publicKey,
46
+ user: signer.publicKey,
47
+ payer: signer.publicKey,
39
48
  });
40
49
 
41
- // Move tokens into the private deposit vault
42
50
  await client.modifyBalance({
43
51
  tokenMint,
52
+ user: signer.publicKey,
53
+ payer: signer.publicKey,
54
+ userTokenAccount: new PublicKey("<sender-ata>"),
44
55
  amount: 1_000_000,
45
56
  increase: true,
46
- user: myKeypair.publicKey,
47
- payer: myKeypair.publicKey,
48
57
  });
49
58
 
50
- // Create permission + delegate deposit to the PER validator
51
59
  await client.createPermission({
52
60
  tokenMint,
53
- user: myKeypair.publicKey,
54
- payer: myKeypair.publicKey,
61
+ user: signer.publicKey,
62
+ payer: signer.publicKey,
55
63
  });
64
+
56
65
  await client.delegateDeposit({
57
66
  tokenMint,
58
- user: myKeypair.publicKey,
59
- payer: myKeypair.publicKey,
60
- validator: new PublicKey("<validator>")
67
+ user: signer.publicKey,
68
+ payer: signer.publicKey,
69
+ validator: ER_VALIDATOR,
61
70
  });
62
71
 
63
- // Use the PER API for operations on delegated accounts
64
- const perClient = await LoyalPrivateTransactionsClient.fromEphemeral({
65
- signer: myKeypair,
66
- rpcEndpoint: "http://127.0.0.1:7799",
67
- wsEndpoint: "ws://127.0.0.1:7800",
68
- });
69
-
70
- // Ensure the destination username deposit exists (and is delegated on PER)
71
- // e.g. via depositForUsername + createUsernamePermission + delegateUsernameDeposit.
72
- await perClient.transferToUsernameDeposit({
72
+ // Private transfer (on PER) destination username deposit must already exist and be delegated
73
+ await client.transferToUsernameDeposit({
73
74
  tokenMint,
74
- username: "alice",
75
+ username: "alice_user",
75
76
  amount: 100_000,
76
- user: myKeypair.publicKey,
77
- payer: myKeypair.publicKey,
77
+ user: signer.publicKey,
78
+ payer: signer.publicKey,
78
79
  sessionToken: null,
79
80
  });
80
81
 
81
- // Undelegate and commit back to the base chain
82
- await perClient.undelegateDeposit({
82
+ // Unshield: commit PER state and withdraw tokens
83
+ await client.undelegateDeposit({
83
84
  tokenMint,
84
- user: myKeypair.publicKey,
85
- payer: myKeypair.publicKey,
85
+ user: signer.publicKey,
86
+ payer: signer.publicKey,
87
+ sessionToken: null,
86
88
  magicProgram: MAGIC_PROGRAM_ID,
87
89
  magicContext: MAGIC_CONTEXT_ID,
88
90
  });
91
+
92
+ await client.modifyBalance({
93
+ tokenMint,
94
+ user: signer.publicKey,
95
+ payer: signer.publicKey,
96
+ userTokenAccount: new PublicKey("<sender-ata>"),
97
+ amount: 1_000_000,
98
+ increase: false,
99
+ });
89
100
  ```
90
101
 
91
102
  ## PER Authentication
92
103
 
93
- When using MagicBlock hosted PER endpoints, you must attach an auth token. The SDK can fetch it automatically.
104
+ For hosted PER endpoints (`tee.magicblock.app`, `mainnet-tee.magicblock.app`), the SDK acquires auth tokens automatically during `fromConfig`.
94
105
 
95
- ```ts
96
- const perClient = await LoyalPrivateTransactionsClient.fromEphemeral({
97
- signer: walletAdapter,
98
- rpcEndpoint: "https://tee.magicblock.app",
99
- wsEndpoint: "wss://tee.magicblock.app",
100
- useAuth: true,
101
- // If your signer does not expose signMessage, pass authToken or signMessage explicitly.
102
- // signMessage: walletAdapter.signMessage,
103
- });
104
- ```
105
-
106
- You can also pre-fetch the token:
106
+ If you need explicit control, fetch the token externally and pass it through `authToken`:
107
107
 
108
108
  ```ts
109
- import { getAuthToken } from "@loyal-labs/private-transactions";
109
+ import { getAuthToken } from "@magicblock-labs/ephemeral-rollups-sdk";
110
110
 
111
- const { token } = await getAuthToken(
112
- "https://tee.magicblock.app",
111
+ const authToken = await getAuthToken(
112
+ "https://mainnet-tee.magicblock.app",
113
113
  wallet.publicKey,
114
114
  wallet.signMessage
115
115
  );
116
116
 
117
- const perClient = await LoyalPrivateTransactionsClient.fromEphemeral({
117
+ const client = await LoyalPrivateTransactionsClient.fromConfig({
118
118
  signer: wallet,
119
- rpcEndpoint: "https://tee.magicblock.app",
120
- wsEndpoint: "wss://tee.magicblock.app",
121
- authToken: token,
119
+ baseRpcEndpoint: "https://api.mainnet-beta.solana.com",
120
+ ephemeralRpcEndpoint: "https://mainnet-tee.magicblock.app",
121
+ ephemeralWsEndpoint: "wss://mainnet-tee.magicblock.app",
122
+ authToken,
122
123
  });
123
124
  ```
124
125
 
125
126
  ## API Overview
126
127
 
127
- ### Factory Methods
128
-
129
- - `fromProvider(provider)`
130
- - `from(connection, signer)`
131
- - `fromWallet(connection, wallet)`
132
- - `fromKeypair(connection, keypair)`
133
- - `fromEphemeral({ signer, rpcEndpoint, wsEndpoint, useAuth, authToken })`
134
-
135
- ### Core Actions
136
-
137
- - `initializeDeposit`
138
- - `modifyBalance`
139
- - `depositForUsername`
140
- - `claimUsernameDeposit`
141
- - `createPermission`
142
- - `createUsernamePermission`
143
- - `delegateDeposit`
144
- - `delegateUsernameDeposit`
145
- - `transferDeposit`
146
- - `transferToUsernameDeposit`
147
- - `undelegateDeposit`
128
+ ### Factory Method
129
+
130
+ - `fromConfig({ signer, baseRpcEndpoint, ephemeralRpcEndpoint, ... })`
131
+
132
+ ### Shield / Unshield
133
+
134
+ - `initializeDeposit` create deposit account (no-op if exists)
135
+ - `modifyBalance` — deposit (`increase: true`) or withdraw (`increase: false`) real tokens
136
+ - `createPermission` — set up PER access control (idempotent)
137
+ - `delegateDeposit` — delegate to TEE validator
138
+
139
+ ### Private Transfers (on PER)
140
+
141
+ - `transferDeposit` — transfer between user deposits
142
+ - `transferToUsernameDeposit` — transfer to username deposit
143
+ - `claimUsernameDepositToDeposit` — claim from username deposit with verified Telegram session
144
+
145
+ ### Username Deposits
146
+
147
+ - `initializeUsernameDeposit` — create username deposit account
148
+ - `createUsernamePermission` — PER access control for username deposit
149
+ - `delegateUsernameDeposit` — delegate username deposit to PER
150
+ - `undelegateUsernameDeposit` — commit and undelegate username deposit
151
+
152
+ ### Commit / Undelegate
153
+
154
+ - `undelegateDeposit` — commit PER state, return deposit to base layer
148
155
  - `undelegateUsernameDeposit`
149
156
 
150
157
  ### Queries
151
158
 
152
- - `getDeposit(user, tokenMint)`
153
- - `getUsernameDeposit(username, tokenMint)`
159
+ - `getBaseDeposit` / `getEphemeralDeposit`
160
+ - `getBaseUsernameDeposit` / `getEphemeralUsernameDeposit`
161
+
162
+ ### Accessors
163
+
164
+ - `publicKey`
165
+ - `getBaseProgram()`
166
+ - `getEphemeralProgram()`
167
+ - `getProgramId()`
154
168
 
155
169
  ### PDA Helpers
156
170
 
157
- - `findDepositPda(user, tokenMint)`
158
- - `findUsernameDepositPda(username, tokenMint)`
159
- - `findVaultPda(tokenMint)`
171
+ - `findDepositPda`
172
+ - `findUsernameDepositPda`
173
+ - `findVaultPda`
174
+ - `findPermissionPda`
175
+ - `findDelegationRecordPda`
176
+ - `findDelegationMetadataPda`
177
+ - `findBufferPda`
160
178
 
161
179
  ## Development
162
180
 
package/dist/index.d.ts CHANGED
@@ -5,37 +5,32 @@
5
5
  * MagicBlock's Private Ephemeral Rollups (PER) for confidential transactions.
6
6
  *
7
7
  * @example
8
- * // Base layer client for setup operations
9
- * import { LoyalPrivateTransactionsClient } from '@loyal-labs/private-transactions';
10
- * import { Connection, Keypair } from '@solana/web3.js';
8
+ * // Create one client that has base + ephemeral program access
9
+ * import { Keypair, PublicKey } from "@solana/web3.js";
10
+ * import {
11
+ * ER_VALIDATOR,
12
+ * LoyalPrivateTransactionsClient,
13
+ * MAGIC_CONTEXT_ID,
14
+ * MAGIC_PROGRAM_ID,
15
+ * } from "@loyal-labs/private-transactions";
11
16
  *
12
- * const connection = new Connection('https://api.devnet.solana.com');
13
- * const client = LoyalPrivateTransactionsClient.from(connection, keypair);
17
+ * const signer = Keypair.fromSecretKey(Uint8Array.from([...secretBytes]));
18
+ * const tokenMint = new PublicKey("<token-mint>");
14
19
  *
15
- * // Initialize and fund deposit
16
- * await client.initializeDeposit({ user, tokenMint, payer });
17
- * await client.modifyBalance({ user, tokenMint, amount, increase: true, ... });
18
- *
19
- * // Create permission and delegate to ephemeral rollup
20
- * await client.createPermission({ user, tokenMint, payer });
21
- * await client.delegateDeposit({ user, tokenMint, payer, validator });
22
- *
23
- * @example
24
- * // Ephemeral rollup client for private operations
25
- * const ephemeralClient = await LoyalPrivateTransactionsClient.fromEphemeral({
26
- * signer: keypair,
27
- * rpcEndpoint: 'http://localhost:7799',
28
- * wsEndpoint: 'ws://localhost:7800',
20
+ * const client = await LoyalPrivateTransactionsClient.fromConfig({
21
+ * signer,
22
+ * baseRpcEndpoint: "https://api.devnet.solana.com",
23
+ * ephemeralRpcEndpoint: "https://mainnet-tee.magicblock.app",
24
+ * ephemeralWsEndpoint: "wss://mainnet-tee.magicblock.app",
29
25
  * });
30
26
  *
31
- * // Execute private transfer
32
- * await ephemeralClient.transferToUsernameDeposit({ username, tokenMint, amount, ... });
33
- *
34
- * // Commit and undelegate
35
- * await ephemeralClient.undelegateDeposit({ user, tokenMint, ... });
27
+ * await client.createPermission({ user: signer.publicKey, tokenMint, payer: signer.publicKey });
28
+ * await client.delegateDeposit({ user: signer.publicKey, tokenMint, payer: signer.publicKey, validator: ER_VALIDATOR });
29
+ * await client.transferToUsernameDeposit({ username: "alice_user", tokenMint, amount: 100_000, user: signer.publicKey, payer: signer.publicKey, sessionToken: null });
30
+ * await client.undelegateDeposit({ user: signer.publicKey, tokenMint, payer: signer.publicKey, sessionToken: null, magicProgram: MAGIC_PROGRAM_ID, magicContext: MAGIC_CONTEXT_ID });
36
31
  */
37
32
  export { LoyalPrivateTransactionsClient, waitForAccountOwnerChange, } from "./src/LoyalPrivateTransactionsClient";
38
- export type { WalletSigner, WalletLike, RpcOptions, ClientConfig, DepositData, UsernameDepositData, InitializeDepositParams, ModifyBalanceParams, ModifyBalanceResult, DepositForUsernameParams, ClaimUsernameDepositParams, CreatePermissionParams, CreateUsernamePermissionParams, DelegateDepositParams, DelegateUsernameDepositParams, UndelegateDepositParams, UndelegateUsernameDepositParams, TransferDepositParams, TransferToUsernameDepositParams, DelegationRecord, DelegationStatusResult, DelegationStatusResponse, } from "./src/types";
33
+ export type { WalletSigner, WalletLike, RpcOptions, ClientConfig, DepositData, UsernameDepositData, InitializeDepositParams, ModifyBalanceParams, ModifyBalanceResult, CreatePermissionParams, CreateUsernamePermissionParams, DelegateDepositParams, DelegateUsernameDepositParams, UndelegateDepositParams, UndelegateUsernameDepositParams, TransferDepositParams, TransferToUsernameDepositParams, DelegationRecord, DelegationStatusResult, DelegationStatusResponse, } from "./src/types";
39
34
  export { isKeypair, isAnchorProvider, isWalletLike } from "./src/types";
40
35
  export { ER_VALIDATOR, PROGRAM_ID, DELEGATION_PROGRAM_ID, PERMISSION_PROGRAM_ID, MAGIC_PROGRAM_ID, MAGIC_CONTEXT_ID, DEPOSIT_SEED, DEPOSIT_SEED_BYTES, USERNAME_DEPOSIT_SEED, USERNAME_DEPOSIT_SEED_BYTES, VAULT_SEED, VAULT_SEED_BYTES, PERMISSION_SEED, PERMISSION_SEED_BYTES, LAMPORTS_PER_SOL, solToLamports, lamportsToSol, } from "./src/constants";
41
36
  export { findDepositPda, findUsernameDepositPda, findVaultPda, findPermissionPda, findDelegationRecordPda, findDelegationMetadataPda, findBufferPda, } from "./src/pda";
@@ -51,94 +46,6 @@ export declare const IDL: {
51
46
  name: string;
52
47
  docs: string[];
53
48
  discriminator: number[];
54
- accounts: ({
55
- name: string;
56
- writable: boolean;
57
- pda?: undefined;
58
- relations?: undefined;
59
- address?: undefined;
60
- } | {
61
- name: string;
62
- writable: boolean;
63
- pda: {
64
- seeds: ({
65
- kind: string;
66
- value: number[];
67
- path?: undefined;
68
- } | {
69
- kind: string;
70
- path: string;
71
- value?: undefined;
72
- })[];
73
- program?: undefined;
74
- };
75
- relations?: undefined;
76
- address?: undefined;
77
- } | {
78
- name: string;
79
- writable: boolean;
80
- pda: {
81
- seeds: ({
82
- kind: string;
83
- path: string;
84
- value?: undefined;
85
- } | {
86
- kind: string;
87
- value: number[];
88
- path?: undefined;
89
- })[];
90
- program: {
91
- kind: string;
92
- value: number[];
93
- };
94
- };
95
- relations?: undefined;
96
- address?: undefined;
97
- } | {
98
- name: string;
99
- writable: boolean;
100
- pda: {
101
- seeds: ({
102
- kind: string;
103
- value: number[];
104
- path?: undefined;
105
- account?: undefined;
106
- } | {
107
- kind: string;
108
- path: string;
109
- account: string;
110
- value?: undefined;
111
- })[];
112
- program?: undefined;
113
- };
114
- relations?: undefined;
115
- address?: undefined;
116
- } | {
117
- name: string;
118
- relations: string[];
119
- writable?: undefined;
120
- pda?: undefined;
121
- address?: undefined;
122
- } | {
123
- name: string;
124
- writable?: undefined;
125
- pda?: undefined;
126
- relations?: undefined;
127
- address?: undefined;
128
- } | {
129
- name: string;
130
- address: string;
131
- writable?: undefined;
132
- pda?: undefined;
133
- relations?: undefined;
134
- })[];
135
- args: {
136
- name: string;
137
- type: string;
138
- }[];
139
- } | {
140
- name: string;
141
- discriminator: number[];
142
49
  accounts: ({
143
50
  name: string;
144
51
  relations: string[];
@@ -180,7 +87,6 @@ export declare const IDL: {
180
87
  name: string;
181
88
  type: string;
182
89
  }[];
183
- docs?: undefined;
184
90
  } | {
185
91
  name: string;
186
92
  docs: string[];
@@ -332,76 +238,6 @@ export declare const IDL: {
332
238
  name: string;
333
239
  type: string;
334
240
  }[];
335
- } | {
336
- name: string;
337
- docs: string[];
338
- discriminator: number[];
339
- accounts: ({
340
- name: string;
341
- writable: boolean;
342
- signer: boolean;
343
- pda?: undefined;
344
- address?: undefined;
345
- } | {
346
- name: string;
347
- writable: boolean;
348
- pda: {
349
- seeds: ({
350
- kind: string;
351
- value: number[];
352
- path?: undefined;
353
- } | {
354
- kind: string;
355
- path: string;
356
- value?: undefined;
357
- })[];
358
- program?: undefined;
359
- };
360
- signer?: undefined;
361
- address?: undefined;
362
- } | {
363
- name: string;
364
- writable: boolean;
365
- pda: {
366
- seeds: ({
367
- kind: string;
368
- path: string;
369
- value?: undefined;
370
- } | {
371
- kind: string;
372
- value: number[];
373
- path?: undefined;
374
- })[];
375
- program: {
376
- kind: string;
377
- value: number[];
378
- };
379
- };
380
- signer?: undefined;
381
- address?: undefined;
382
- } | {
383
- name: string;
384
- writable: boolean;
385
- signer?: undefined;
386
- pda?: undefined;
387
- address?: undefined;
388
- } | {
389
- name: string;
390
- writable?: undefined;
391
- signer?: undefined;
392
- pda?: undefined;
393
- address?: undefined;
394
- } | {
395
- name: string;
396
- address: string;
397
- writable?: undefined;
398
- signer?: undefined;
399
- pda?: undefined;
400
- })[];
401
- args: {
402
- name: string;
403
- type: string;
404
- }[];
405
241
  } | {
406
242
  name: string;
407
243
  discriminator: number[];