@yellow-org/sdk 1.1.1 → 1.2.0
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 +119 -17
- package/dist/app/packing.d.ts +2 -0
- package/dist/app/packing.js +39 -5
- package/dist/app/types.d.ts +2 -4
- package/dist/blockchain/evm/app_registry_abi.d.ts +88 -0
- package/dist/blockchain/evm/app_registry_abi.js +68 -0
- package/dist/blockchain/evm/index.d.ts +2 -0
- package/dist/blockchain/evm/index.js +2 -0
- package/dist/blockchain/evm/locking_client.d.ts +21 -0
- package/dist/blockchain/evm/locking_client.js +124 -0
- package/dist/client.d.ts +25 -2
- package/dist/client.js +110 -16
- package/dist/core/types.d.ts +7 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/rpc/api.d.ts +23 -1
- package/dist/rpc/client.d.ts +3 -0
- package/dist/rpc/client.js +9 -0
- package/dist/rpc/methods.d.ts +4 -0
- package/dist/rpc/methods.js +4 -0
- package/dist/rpc/types.d.ts +18 -0
- package/dist/signers.d.ts +16 -0
- package/dist/signers.js +30 -0
- package/dist/utils.d.ts +2 -1
- package/dist/utils.js +15 -8
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Yellow TypeScript SDK
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@yellow-org/sdk)
|
|
4
|
-
[](https://github.com/
|
|
4
|
+
[](https://github.com/layer-3/nitrolite/blob/main/LICENSE)
|
|
5
5
|
|
|
6
6
|
TypeScript SDK for Clearnode payment channels providing both high-level and low-level operations in a unified client:
|
|
7
7
|
- **State Operations**: `deposit()`, `withdraw()`, `transfer()`, `closeHomeChannel()`, `acknowledge()` - build and co-sign states off-chain
|
|
@@ -9,7 +9,7 @@ TypeScript SDK for Clearnode payment channels providing both high-level and low-
|
|
|
9
9
|
- **Low-Level Operations**: Direct RPC access for custom flows and advanced use cases
|
|
10
10
|
- **Full Feature Parity**: 100% compatibility with Go SDK functionality
|
|
11
11
|
|
|
12
|
-
> If you are migrating from `@
|
|
12
|
+
> If you are migrating from `@layer-3/nitrolite@v0.5.3`, please consider using the [@yellow-org/sdk-compat](https://www.npmjs.com/package/@yellow-org/sdk-compat) package. It is a translation layer that uses this SDK underneath and maps the familiar v0.5.3 API surfaces to this SDK.
|
|
13
13
|
|
|
14
14
|
## Method Cheat Sheet
|
|
15
15
|
|
|
@@ -52,11 +52,18 @@ client.getEscrowChannel(escrowChannelId) // Escrow channel info
|
|
|
52
52
|
client.getLatestState(wallet, asset, onlySigned) // Latest state
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
### App Registry
|
|
56
|
+
```typescript
|
|
57
|
+
client.getApps(opts) // List registered apps
|
|
58
|
+
client.registerApp(appID, metadata, approvalNotRequired) // Register new app
|
|
59
|
+
```
|
|
60
|
+
|
|
55
61
|
### App Sessions
|
|
56
62
|
```typescript
|
|
57
63
|
client.getAppSessions(opts) // List sessions
|
|
58
64
|
client.getAppDefinition(appSessionId) // Session definition
|
|
59
65
|
client.createAppSession(definition, sessionData, sigs) // Create session
|
|
66
|
+
client.createAppSession(def, data, sigs, { ownerSig }) // Create with owner approval
|
|
60
67
|
client.submitAppSessionDeposit(update, sigs, asset, amount) // Deposit to session
|
|
61
68
|
client.submitAppState(update, sigs) // Update session
|
|
62
69
|
client.rebalanceAppSessions(signedUpdates) // Atomic rebalance
|
|
@@ -145,7 +152,7 @@ main().catch(console.error);
|
|
|
145
152
|
```
|
|
146
153
|
sdk/ts/src/
|
|
147
154
|
├── client.ts # Core client, constructors, high-level operations
|
|
148
|
-
├── signers.ts #
|
|
155
|
+
├── signers.ts # Signers (EthereumMsg/Raw, Channel, AppSession)
|
|
149
156
|
├── config.ts # Configuration options
|
|
150
157
|
├── asset_store.ts # Asset metadata caching
|
|
151
158
|
├── utils.ts # Type transformations
|
|
@@ -391,6 +398,21 @@ const state = await client.getLatestState(wallet, asset, onlySigned);
|
|
|
391
398
|
|
|
392
399
|
**Note:** State submission and channel creation are handled internally by state operations (`deposit()`, `withdraw()`, `transfer()`). On-chain settlement is handled by `checkpoint()`.
|
|
393
400
|
|
|
401
|
+
### App Registry
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
// List registered applications with optional filtering
|
|
405
|
+
const { apps, metadata } = await client.getApps({
|
|
406
|
+
appId: 'my-app',
|
|
407
|
+
ownerWallet: '0x1234...',
|
|
408
|
+
page: 1,
|
|
409
|
+
pageSize: 10,
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
// Register a new application
|
|
413
|
+
await client.registerApp('my-app', '{"name": "My App"}', false);
|
|
414
|
+
```
|
|
415
|
+
|
|
394
416
|
### App Sessions (Low-Level)
|
|
395
417
|
|
|
396
418
|
```typescript
|
|
@@ -417,6 +439,50 @@ await client.submitAppState(appUpdate, quorumSigs);
|
|
|
417
439
|
const batchId = await client.rebalanceAppSessions(signedUpdates);
|
|
418
440
|
```
|
|
419
441
|
|
|
442
|
+
#### Owner Approval for App Session Creation
|
|
443
|
+
|
|
444
|
+
When an app is registered with `creationApprovalNotRequired: false`, the app owner must sign the session creation request. Pass the owner's signature via the options parameter:
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
import { AppSessionWalletSignerV1, EthereumMsgSigner } from '@yellow-org/sdk';
|
|
448
|
+
|
|
449
|
+
// Owner signs the create request using their app session signer
|
|
450
|
+
const ownerMsgSigner = new EthereumMsgSigner(ownerPrivateKey);
|
|
451
|
+
const ownerAppSessionSigner = new AppSessionWalletSignerV1(ownerMsgSigner);
|
|
452
|
+
const ownerSig = await ownerAppSessionSigner.signMessage(createRequest);
|
|
453
|
+
|
|
454
|
+
const { appSessionId } = await client.createAppSession(
|
|
455
|
+
definition,
|
|
456
|
+
sessionData,
|
|
457
|
+
quorumSigs,
|
|
458
|
+
{ ownerSig }
|
|
459
|
+
);
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### App Session Signers
|
|
463
|
+
|
|
464
|
+
App session operations require signatures with a type byte prefix, similar to channel signers:
|
|
465
|
+
|
|
466
|
+
| Type | Byte | Class | Usage |
|
|
467
|
+
|------|------|-------|-------|
|
|
468
|
+
| Wallet | `0xA1` | `AppSessionWalletSignerV1` | Main wallet signs app session operations |
|
|
469
|
+
| Session Key | `0xA2` | `AppSessionKeySignerV1` | Delegated session key signs on behalf of wallet |
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
import { EthereumMsgSigner, AppSessionWalletSignerV1, AppSessionKeySignerV1 } from '@yellow-org/sdk';
|
|
473
|
+
|
|
474
|
+
// Create app session wallet signer
|
|
475
|
+
const msgSigner = new EthereumMsgSigner(privateKey);
|
|
476
|
+
const appSessionSigner = new AppSessionWalletSignerV1(msgSigner);
|
|
477
|
+
|
|
478
|
+
// Sign app session operations (create, deposit, state updates, etc.)
|
|
479
|
+
const sig = await appSessionSigner.signMessage(packedRequest);
|
|
480
|
+
|
|
481
|
+
// For session key delegation
|
|
482
|
+
const sessionKeyMsgSigner = new EthereumMsgSigner(sessionKeyPrivateKey);
|
|
483
|
+
const sessionKeySigner = new AppSessionKeySignerV1(sessionKeyMsgSigner);
|
|
484
|
+
```
|
|
485
|
+
|
|
420
486
|
### App Session Keys
|
|
421
487
|
|
|
422
488
|
```typescript
|
|
@@ -734,8 +800,17 @@ queryTransactions().catch(console.error);
|
|
|
734
800
|
|
|
735
801
|
### Example 4: App Session Workflow
|
|
736
802
|
|
|
803
|
+
For a comprehensive multi-party app session example including app registration, owner approval,
|
|
804
|
+
session key delegation, deposits, redistribution, and more, see
|
|
805
|
+
[examples/app_sessions/lifecycle.ts](examples/app_sessions/lifecycle.ts).
|
|
806
|
+
|
|
737
807
|
```typescript
|
|
738
|
-
import {
|
|
808
|
+
import {
|
|
809
|
+
Client, createSigners, EthereumMsgSigner,
|
|
810
|
+
AppSessionWalletSignerV1, withBlockchainRPC
|
|
811
|
+
} from '@yellow-org/sdk';
|
|
812
|
+
import { AppStateUpdateIntent } from '@yellow-org/sdk/app/types';
|
|
813
|
+
import { packCreateAppSessionRequestV1, packAppStateUpdateV1 } from '@yellow-org/sdk/app/packing';
|
|
739
814
|
import Decimal from 'decimal.js';
|
|
740
815
|
|
|
741
816
|
async function appSessionExample() {
|
|
@@ -748,42 +823,55 @@ async function appSessionExample() {
|
|
|
748
823
|
);
|
|
749
824
|
|
|
750
825
|
try {
|
|
826
|
+
// Register app (required before creating sessions)
|
|
827
|
+
await client.registerApp('chess-v1', '{}', true);
|
|
828
|
+
|
|
829
|
+
// Create app session signer
|
|
830
|
+
const msgSigner = new EthereumMsgSigner(process.env.PRIVATE_KEY!);
|
|
831
|
+
const appSessionSigner = new AppSessionWalletSignerV1(msgSigner);
|
|
832
|
+
|
|
751
833
|
// Create app session
|
|
752
834
|
const definition = {
|
|
753
|
-
|
|
835
|
+
applicationId: 'chess-v1',
|
|
754
836
|
participants: [
|
|
755
|
-
{ walletAddress: client.getUserAddress(), signatureWeight:
|
|
756
|
-
{ walletAddress: '0xOpponent...', signatureWeight: 1 },
|
|
837
|
+
{ walletAddress: client.getUserAddress(), signatureWeight: 100 },
|
|
757
838
|
],
|
|
758
|
-
quorum:
|
|
759
|
-
nonce:
|
|
839
|
+
quorum: 100,
|
|
840
|
+
nonce: BigInt(Date.now() * 1000000),
|
|
760
841
|
};
|
|
761
842
|
|
|
843
|
+
const createRequest = packCreateAppSessionRequestV1(definition, '{}');
|
|
844
|
+
const createSig = await appSessionSigner.signMessage(createRequest);
|
|
845
|
+
|
|
762
846
|
const { appSessionId } = await client.createAppSession(
|
|
763
847
|
definition,
|
|
764
848
|
'{}',
|
|
765
|
-
[
|
|
849
|
+
[createSig]
|
|
766
850
|
);
|
|
767
851
|
console.log('Session created:', appSessionId);
|
|
768
852
|
|
|
769
853
|
// Deposit to app session
|
|
854
|
+
const depositAmount = new Decimal(50);
|
|
770
855
|
const appUpdate = {
|
|
771
856
|
appSessionId,
|
|
772
|
-
intent:
|
|
773
|
-
version:
|
|
857
|
+
intent: AppStateUpdateIntent.Deposit,
|
|
858
|
+
version: 2n,
|
|
774
859
|
allocations: [{
|
|
775
860
|
participant: client.getUserAddress(),
|
|
776
861
|
asset: 'usdc',
|
|
777
|
-
amount:
|
|
862
|
+
amount: depositAmount,
|
|
778
863
|
}],
|
|
779
864
|
sessionData: '{}',
|
|
780
865
|
};
|
|
781
866
|
|
|
867
|
+
const depositRequest = packAppStateUpdateV1(appUpdate);
|
|
868
|
+
const depositSig = await appSessionSigner.signMessage(depositRequest);
|
|
869
|
+
|
|
782
870
|
const nodeSig = await client.submitAppSessionDeposit(
|
|
783
871
|
appUpdate,
|
|
784
|
-
[
|
|
872
|
+
[depositSig],
|
|
785
873
|
'usdc',
|
|
786
|
-
|
|
874
|
+
depositAmount
|
|
787
875
|
);
|
|
788
876
|
console.log('Deposit signature:', nodeSig);
|
|
789
877
|
|
|
@@ -854,6 +942,20 @@ import type {
|
|
|
854
942
|
ChannelSessionKeyStateV1,
|
|
855
943
|
PaginationMetadata,
|
|
856
944
|
} from '@yellow-org/sdk';
|
|
945
|
+
|
|
946
|
+
// Signer types
|
|
947
|
+
import {
|
|
948
|
+
EthereumMsgSigner,
|
|
949
|
+
EthereumRawSigner,
|
|
950
|
+
ChannelDefaultSigner,
|
|
951
|
+
ChannelSessionKeyStateSigner,
|
|
952
|
+
AppSessionWalletSignerV1,
|
|
953
|
+
AppSessionKeySignerV1,
|
|
954
|
+
createSigners,
|
|
955
|
+
} from '@yellow-org/sdk';
|
|
956
|
+
|
|
957
|
+
// App Registry types (from rpc/types)
|
|
958
|
+
import type { AppV1, AppInfoV1 } from '@yellow-org/sdk';
|
|
857
959
|
```
|
|
858
960
|
|
|
859
961
|
### BigInt for Chain IDs
|
|
@@ -976,8 +1078,8 @@ Part of the Nitrolite project. See [LICENSE](../../LICENSE) for details.
|
|
|
976
1078
|
## Related Projects
|
|
977
1079
|
|
|
978
1080
|
- [Nitrolite TS Compat](https://www.npmjs.com/package/@yellow-org/sdk-compat) - Compatibility layer for older TypeScript versions
|
|
979
|
-
- [Nitrolite Go SDK](https://github.com/
|
|
980
|
-
- [Nitrolite Smart Contracts](https://github.com/
|
|
1081
|
+
- [Nitrolite Go SDK](https://github.com/layer-3/nitrolite/tree/stable/sdk/go) - Go implementation with same API
|
|
1082
|
+
- [Nitrolite Smart Contracts](https://github.com/layer-3/nitrolite/tree/stable/contracts) - On-chain contracts
|
|
981
1083
|
|
|
982
1084
|
---
|
|
983
1085
|
|
package/dist/app/packing.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { AppDefinitionV1, AppStateUpdateV1, AppSessionKeyStateV1, AppSessionVersionV1 } from './types';
|
|
2
|
+
import { AppV1 } from '../rpc/types';
|
|
2
3
|
export declare function packCreateAppSessionRequestV1(definition: AppDefinitionV1, sessionData: string): `0x${string}`;
|
|
3
4
|
export declare function packAppStateUpdateV1(stateUpdate: AppStateUpdateV1): `0x${string}`;
|
|
4
5
|
export declare function generateAppSessionIDV1(definition: AppDefinitionV1): `0x${string}`;
|
|
5
6
|
export declare function generateRebalanceBatchIDV1(sessionVersions: AppSessionVersionV1[]): `0x${string}`;
|
|
6
7
|
export declare function generateRebalanceTransactionIDV1(batchId: string, sessionId: string, asset: string): `0x${string}`;
|
|
8
|
+
export declare function packAppV1(app: AppV1): `0x${string}`;
|
|
7
9
|
export declare function packAppSessionKeyStateV1(state: AppSessionKeyStateV1): `0x${string}`;
|
package/dist/app/packing.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { encodeAbiParameters, keccak256 } from 'viem';
|
|
1
|
+
import { encodeAbiParameters, keccak256, pad, toHex } from 'viem';
|
|
2
2
|
export function packCreateAppSessionRequestV1(definition, sessionData) {
|
|
3
3
|
const participantComponents = [
|
|
4
4
|
{ name: 'walletAddress', type: 'address' },
|
|
@@ -15,7 +15,7 @@ export function packCreateAppSessionRequestV1(definition, sessionData) {
|
|
|
15
15
|
{ type: 'uint64' },
|
|
16
16
|
{ type: 'string' },
|
|
17
17
|
], [
|
|
18
|
-
definition.
|
|
18
|
+
definition.applicationId,
|
|
19
19
|
participants,
|
|
20
20
|
definition.quorum,
|
|
21
21
|
definition.nonce,
|
|
@@ -64,7 +64,7 @@ export function generateAppSessionIDV1(definition) {
|
|
|
64
64
|
{ type: 'tuple[]', components: participantComponents },
|
|
65
65
|
{ type: 'uint8' },
|
|
66
66
|
{ type: 'uint64' },
|
|
67
|
-
], [definition.
|
|
67
|
+
], [definition.applicationId, participants, definition.quorum, definition.nonce]);
|
|
68
68
|
return keccak256(packed);
|
|
69
69
|
}
|
|
70
70
|
export function generateRebalanceBatchIDV1(sessionVersions) {
|
|
@@ -89,9 +89,43 @@ export function generateRebalanceTransactionIDV1(batchId, sessionId, asset) {
|
|
|
89
89
|
], [batchId, sessionId, asset]);
|
|
90
90
|
return keccak256(packed);
|
|
91
91
|
}
|
|
92
|
+
export function packAppV1(app) {
|
|
93
|
+
const metadataHash = keccak256(toHex(new TextEncoder().encode(app.metadata)));
|
|
94
|
+
const packed = encodeAbiParameters([
|
|
95
|
+
{ type: 'string' },
|
|
96
|
+
{ type: 'address' },
|
|
97
|
+
{ type: 'bytes32' },
|
|
98
|
+
{ type: 'uint64' },
|
|
99
|
+
{ type: 'bool' },
|
|
100
|
+
], [
|
|
101
|
+
app.id,
|
|
102
|
+
app.owner_wallet,
|
|
103
|
+
metadataHash,
|
|
104
|
+
BigInt(app.version),
|
|
105
|
+
app.creation_approval_not_required,
|
|
106
|
+
]);
|
|
107
|
+
return keccak256(packed);
|
|
108
|
+
}
|
|
109
|
+
function hexToBytes32(s) {
|
|
110
|
+
let hex = s.startsWith('0x') || s.startsWith('0X') ? s.slice(2) : s;
|
|
111
|
+
if (hex.length % 2 === 1) {
|
|
112
|
+
hex = '0' + hex;
|
|
113
|
+
}
|
|
114
|
+
if (!/^[0-9a-fA-F]*$/.test(hex)) {
|
|
115
|
+
return pad('0x00', { size: 32 });
|
|
116
|
+
}
|
|
117
|
+
if (hex.length === 0) {
|
|
118
|
+
return pad('0x00', { size: 32 });
|
|
119
|
+
}
|
|
120
|
+
if (hex.length > 64) {
|
|
121
|
+
hex = hex.slice(hex.length - 64);
|
|
122
|
+
}
|
|
123
|
+
const padded = hex.padStart(64, '0');
|
|
124
|
+
return `0x${padded}`;
|
|
125
|
+
}
|
|
92
126
|
export function packAppSessionKeyStateV1(state) {
|
|
93
|
-
const applicationIDHashes = state.application_ids.map(
|
|
94
|
-
const appSessionIDHashes = state.app_session_ids.map(
|
|
127
|
+
const applicationIDHashes = state.application_ids.map(hexToBytes32);
|
|
128
|
+
const appSessionIDHashes = state.app_session_ids.map(hexToBytes32);
|
|
95
129
|
const packed = encodeAbiParameters([
|
|
96
130
|
{ type: 'address' },
|
|
97
131
|
{ type: 'address' },
|
package/dist/app/types.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export interface AppParticipantV1 {
|
|
|
31
31
|
signatureWeight: number;
|
|
32
32
|
}
|
|
33
33
|
export interface AppDefinitionV1 {
|
|
34
|
-
|
|
34
|
+
applicationId: string;
|
|
35
35
|
participants: AppParticipantV1[];
|
|
36
36
|
quorum: number;
|
|
37
37
|
nonce: bigint;
|
|
@@ -58,12 +58,10 @@ export interface SignedAppStateUpdateV1 {
|
|
|
58
58
|
}
|
|
59
59
|
export interface AppSessionInfoV1 {
|
|
60
60
|
appSessionId: string;
|
|
61
|
+
appDefinition: AppDefinitionV1;
|
|
61
62
|
isClosed: boolean;
|
|
62
|
-
participants: AppParticipantV1[];
|
|
63
63
|
sessionData: string;
|
|
64
|
-
quorum: number;
|
|
65
64
|
version: bigint;
|
|
66
|
-
nonce: bigint;
|
|
67
65
|
allocations: AppAllocationV1[];
|
|
68
66
|
}
|
|
69
67
|
export interface SessionKeyV1 {
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export declare const AppRegistryAbi: readonly [{
|
|
2
|
+
readonly type: "function";
|
|
3
|
+
readonly name: "asset";
|
|
4
|
+
readonly inputs: readonly [];
|
|
5
|
+
readonly outputs: readonly [{
|
|
6
|
+
readonly name: "";
|
|
7
|
+
readonly type: "address";
|
|
8
|
+
}];
|
|
9
|
+
readonly stateMutability: "view";
|
|
10
|
+
}, {
|
|
11
|
+
readonly type: "function";
|
|
12
|
+
readonly name: "UNLOCK_PERIOD";
|
|
13
|
+
readonly inputs: readonly [];
|
|
14
|
+
readonly outputs: readonly [{
|
|
15
|
+
readonly name: "";
|
|
16
|
+
readonly type: "uint256";
|
|
17
|
+
}];
|
|
18
|
+
readonly stateMutability: "view";
|
|
19
|
+
}, {
|
|
20
|
+
readonly type: "function";
|
|
21
|
+
readonly name: "balanceOf";
|
|
22
|
+
readonly inputs: readonly [{
|
|
23
|
+
readonly name: "user";
|
|
24
|
+
readonly type: "address";
|
|
25
|
+
}];
|
|
26
|
+
readonly outputs: readonly [{
|
|
27
|
+
readonly name: "";
|
|
28
|
+
readonly type: "uint256";
|
|
29
|
+
}];
|
|
30
|
+
readonly stateMutability: "view";
|
|
31
|
+
}, {
|
|
32
|
+
readonly type: "function";
|
|
33
|
+
readonly name: "lockStateOf";
|
|
34
|
+
readonly inputs: readonly [{
|
|
35
|
+
readonly name: "user";
|
|
36
|
+
readonly type: "address";
|
|
37
|
+
}];
|
|
38
|
+
readonly outputs: readonly [{
|
|
39
|
+
readonly name: "";
|
|
40
|
+
readonly type: "uint8";
|
|
41
|
+
}];
|
|
42
|
+
readonly stateMutability: "view";
|
|
43
|
+
}, {
|
|
44
|
+
readonly type: "function";
|
|
45
|
+
readonly name: "unlockTimestampOf";
|
|
46
|
+
readonly inputs: readonly [{
|
|
47
|
+
readonly name: "user";
|
|
48
|
+
readonly type: "address";
|
|
49
|
+
}];
|
|
50
|
+
readonly outputs: readonly [{
|
|
51
|
+
readonly name: "";
|
|
52
|
+
readonly type: "uint256";
|
|
53
|
+
}];
|
|
54
|
+
readonly stateMutability: "view";
|
|
55
|
+
}, {
|
|
56
|
+
readonly type: "function";
|
|
57
|
+
readonly name: "lock";
|
|
58
|
+
readonly inputs: readonly [{
|
|
59
|
+
readonly name: "target";
|
|
60
|
+
readonly type: "address";
|
|
61
|
+
}, {
|
|
62
|
+
readonly name: "amount";
|
|
63
|
+
readonly type: "uint256";
|
|
64
|
+
}];
|
|
65
|
+
readonly outputs: readonly [];
|
|
66
|
+
readonly stateMutability: "nonpayable";
|
|
67
|
+
}, {
|
|
68
|
+
readonly type: "function";
|
|
69
|
+
readonly name: "relock";
|
|
70
|
+
readonly inputs: readonly [];
|
|
71
|
+
readonly outputs: readonly [];
|
|
72
|
+
readonly stateMutability: "nonpayable";
|
|
73
|
+
}, {
|
|
74
|
+
readonly type: "function";
|
|
75
|
+
readonly name: "unlock";
|
|
76
|
+
readonly inputs: readonly [];
|
|
77
|
+
readonly outputs: readonly [];
|
|
78
|
+
readonly stateMutability: "nonpayable";
|
|
79
|
+
}, {
|
|
80
|
+
readonly type: "function";
|
|
81
|
+
readonly name: "withdraw";
|
|
82
|
+
readonly inputs: readonly [{
|
|
83
|
+
readonly name: "destination";
|
|
84
|
+
readonly type: "address";
|
|
85
|
+
}];
|
|
86
|
+
readonly outputs: readonly [];
|
|
87
|
+
readonly stateMutability: "nonpayable";
|
|
88
|
+
}];
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export const AppRegistryAbi = [
|
|
2
|
+
{
|
|
3
|
+
type: 'function',
|
|
4
|
+
name: 'asset',
|
|
5
|
+
inputs: [],
|
|
6
|
+
outputs: [{ name: '', type: 'address' }],
|
|
7
|
+
stateMutability: 'view',
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
type: 'function',
|
|
11
|
+
name: 'UNLOCK_PERIOD',
|
|
12
|
+
inputs: [],
|
|
13
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
14
|
+
stateMutability: 'view',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: 'function',
|
|
18
|
+
name: 'balanceOf',
|
|
19
|
+
inputs: [{ name: 'user', type: 'address' }],
|
|
20
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
21
|
+
stateMutability: 'view',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: 'function',
|
|
25
|
+
name: 'lockStateOf',
|
|
26
|
+
inputs: [{ name: 'user', type: 'address' }],
|
|
27
|
+
outputs: [{ name: '', type: 'uint8' }],
|
|
28
|
+
stateMutability: 'view',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: 'function',
|
|
32
|
+
name: 'unlockTimestampOf',
|
|
33
|
+
inputs: [{ name: 'user', type: 'address' }],
|
|
34
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
35
|
+
stateMutability: 'view',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: 'function',
|
|
39
|
+
name: 'lock',
|
|
40
|
+
inputs: [
|
|
41
|
+
{ name: 'target', type: 'address' },
|
|
42
|
+
{ name: 'amount', type: 'uint256' },
|
|
43
|
+
],
|
|
44
|
+
outputs: [],
|
|
45
|
+
stateMutability: 'nonpayable',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: 'function',
|
|
49
|
+
name: 'relock',
|
|
50
|
+
inputs: [],
|
|
51
|
+
outputs: [],
|
|
52
|
+
stateMutability: 'nonpayable',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: 'function',
|
|
56
|
+
name: 'unlock',
|
|
57
|
+
inputs: [],
|
|
58
|
+
outputs: [],
|
|
59
|
+
stateMutability: 'nonpayable',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
type: 'function',
|
|
63
|
+
name: 'withdraw',
|
|
64
|
+
inputs: [{ name: 'destination', type: 'address' }],
|
|
65
|
+
outputs: [],
|
|
66
|
+
stateMutability: 'nonpayable',
|
|
67
|
+
},
|
|
68
|
+
];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Address } from 'viem';
|
|
2
|
+
import Decimal from 'decimal.js';
|
|
3
|
+
import { EVMClient, WalletSigner } from './interface';
|
|
4
|
+
export declare class LockingClient {
|
|
5
|
+
private contractAddress;
|
|
6
|
+
private evmClient;
|
|
7
|
+
private walletSigner?;
|
|
8
|
+
private tokenAddress?;
|
|
9
|
+
private tokenDecimals?;
|
|
10
|
+
constructor(contractAddress: Address, evmClient: EVMClient, walletSigner?: WalletSigner);
|
|
11
|
+
private requireWalletSigner;
|
|
12
|
+
private ensureTokenInfo;
|
|
13
|
+
lock(target: Address, amount: Decimal): Promise<string>;
|
|
14
|
+
relock(): Promise<string>;
|
|
15
|
+
unlock(): Promise<string>;
|
|
16
|
+
withdraw(destination: Address): Promise<string>;
|
|
17
|
+
approveToken(amount: Decimal): Promise<string>;
|
|
18
|
+
getBalance(user: Address): Promise<Decimal>;
|
|
19
|
+
getLockState(user: Address): Promise<number>;
|
|
20
|
+
getTokenDecimals(): Promise<number>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import Decimal from 'decimal.js';
|
|
2
|
+
import { decimalToBigInt } from '../../core/utils';
|
|
3
|
+
import { AppRegistryAbi } from './app_registry_abi';
|
|
4
|
+
import { Erc20Abi } from './erc20_abi';
|
|
5
|
+
export class LockingClient {
|
|
6
|
+
constructor(contractAddress, evmClient, walletSigner) {
|
|
7
|
+
this.contractAddress = contractAddress;
|
|
8
|
+
this.evmClient = evmClient;
|
|
9
|
+
this.walletSigner = walletSigner;
|
|
10
|
+
}
|
|
11
|
+
requireWalletSigner() {
|
|
12
|
+
if (!this.walletSigner) {
|
|
13
|
+
throw new Error('Write operations require a wallet signer. In Node.js, use a TransactionSigner that implements getAccount() (e.g., EthereumRawSigner)');
|
|
14
|
+
}
|
|
15
|
+
return this.walletSigner;
|
|
16
|
+
}
|
|
17
|
+
async ensureTokenInfo() {
|
|
18
|
+
if (this.tokenAddress !== undefined && this.tokenDecimals !== undefined) {
|
|
19
|
+
return { address: this.tokenAddress, decimals: this.tokenDecimals };
|
|
20
|
+
}
|
|
21
|
+
const tokenAddress = await this.evmClient.readContract({
|
|
22
|
+
address: this.contractAddress,
|
|
23
|
+
abi: AppRegistryAbi,
|
|
24
|
+
functionName: 'asset',
|
|
25
|
+
});
|
|
26
|
+
const decimals = await this.evmClient.readContract({
|
|
27
|
+
address: tokenAddress,
|
|
28
|
+
abi: Erc20Abi,
|
|
29
|
+
functionName: 'decimals',
|
|
30
|
+
});
|
|
31
|
+
this.tokenAddress = tokenAddress;
|
|
32
|
+
this.tokenDecimals = decimals;
|
|
33
|
+
return { address: tokenAddress, decimals };
|
|
34
|
+
}
|
|
35
|
+
async lock(target, amount) {
|
|
36
|
+
const walletSigner = this.requireWalletSigner();
|
|
37
|
+
const { decimals } = await this.ensureTokenInfo();
|
|
38
|
+
const amountBig = decimalToBigInt(amount, decimals);
|
|
39
|
+
const { request } = await this.evmClient.simulateContract({
|
|
40
|
+
address: this.contractAddress,
|
|
41
|
+
abi: AppRegistryAbi,
|
|
42
|
+
functionName: 'lock',
|
|
43
|
+
args: [target, amountBig],
|
|
44
|
+
account: walletSigner.account.address,
|
|
45
|
+
});
|
|
46
|
+
const hash = await walletSigner.writeContract(request);
|
|
47
|
+
await this.evmClient.waitForTransactionReceipt({ hash });
|
|
48
|
+
return hash;
|
|
49
|
+
}
|
|
50
|
+
async relock() {
|
|
51
|
+
const walletSigner = this.requireWalletSigner();
|
|
52
|
+
const { request } = await this.evmClient.simulateContract({
|
|
53
|
+
address: this.contractAddress,
|
|
54
|
+
abi: AppRegistryAbi,
|
|
55
|
+
functionName: 'relock',
|
|
56
|
+
account: walletSigner.account.address,
|
|
57
|
+
});
|
|
58
|
+
const hash = await walletSigner.writeContract(request);
|
|
59
|
+
await this.evmClient.waitForTransactionReceipt({ hash });
|
|
60
|
+
return hash;
|
|
61
|
+
}
|
|
62
|
+
async unlock() {
|
|
63
|
+
const walletSigner = this.requireWalletSigner();
|
|
64
|
+
const { request } = await this.evmClient.simulateContract({
|
|
65
|
+
address: this.contractAddress,
|
|
66
|
+
abi: AppRegistryAbi,
|
|
67
|
+
functionName: 'unlock',
|
|
68
|
+
account: walletSigner.account.address,
|
|
69
|
+
});
|
|
70
|
+
const hash = await walletSigner.writeContract(request);
|
|
71
|
+
await this.evmClient.waitForTransactionReceipt({ hash });
|
|
72
|
+
return hash;
|
|
73
|
+
}
|
|
74
|
+
async withdraw(destination) {
|
|
75
|
+
const walletSigner = this.requireWalletSigner();
|
|
76
|
+
const { request } = await this.evmClient.simulateContract({
|
|
77
|
+
address: this.contractAddress,
|
|
78
|
+
abi: AppRegistryAbi,
|
|
79
|
+
functionName: 'withdraw',
|
|
80
|
+
args: [destination],
|
|
81
|
+
account: walletSigner.account.address,
|
|
82
|
+
});
|
|
83
|
+
const hash = await walletSigner.writeContract(request);
|
|
84
|
+
await this.evmClient.waitForTransactionReceipt({ hash });
|
|
85
|
+
return hash;
|
|
86
|
+
}
|
|
87
|
+
async approveToken(amount) {
|
|
88
|
+
const walletSigner = this.requireWalletSigner();
|
|
89
|
+
const { address: tokenAddress, decimals } = await this.ensureTokenInfo();
|
|
90
|
+
const amountBig = decimalToBigInt(amount, decimals);
|
|
91
|
+
const { request } = await this.evmClient.simulateContract({
|
|
92
|
+
address: tokenAddress,
|
|
93
|
+
abi: Erc20Abi,
|
|
94
|
+
functionName: 'approve',
|
|
95
|
+
args: [this.contractAddress, amountBig],
|
|
96
|
+
account: walletSigner.account.address,
|
|
97
|
+
});
|
|
98
|
+
const hash = await walletSigner.writeContract(request);
|
|
99
|
+
await this.evmClient.waitForTransactionReceipt({ hash });
|
|
100
|
+
return hash;
|
|
101
|
+
}
|
|
102
|
+
async getBalance(user) {
|
|
103
|
+
const { decimals } = await this.ensureTokenInfo();
|
|
104
|
+
const balance = await this.evmClient.readContract({
|
|
105
|
+
address: this.contractAddress,
|
|
106
|
+
abi: AppRegistryAbi,
|
|
107
|
+
functionName: 'balanceOf',
|
|
108
|
+
args: [user],
|
|
109
|
+
});
|
|
110
|
+
return new Decimal(balance.toString()).div(Decimal.pow(10, decimals));
|
|
111
|
+
}
|
|
112
|
+
async getLockState(user) {
|
|
113
|
+
return await this.evmClient.readContract({
|
|
114
|
+
address: this.contractAddress,
|
|
115
|
+
abi: AppRegistryAbi,
|
|
116
|
+
functionName: 'lockStateOf',
|
|
117
|
+
args: [user],
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
async getTokenDecimals() {
|
|
121
|
+
const { decimals } = await this.ensureTokenInfo();
|
|
122
|
+
return decimals;
|
|
123
|
+
}
|
|
124
|
+
}
|
package/dist/client.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Address, Hex } from 'viem';
|
|
|
2
2
|
import Decimal from 'decimal.js';
|
|
3
3
|
import * as core from './core';
|
|
4
4
|
import * as app from './app';
|
|
5
|
-
import { ChannelSessionKeyStateV1 } from './rpc/types';
|
|
5
|
+
import { ChannelSessionKeyStateV1, AppInfoV1 } from './rpc/types';
|
|
6
6
|
import { Option } from './config';
|
|
7
7
|
import { StateSigner, TransactionSigner } from './signers';
|
|
8
8
|
export declare const DEFAULT_CHALLENGE_PERIOD = 86400;
|
|
@@ -13,6 +13,7 @@ export declare class Client {
|
|
|
13
13
|
private exitPromise;
|
|
14
14
|
private exitResolve?;
|
|
15
15
|
private blockchainClients;
|
|
16
|
+
private blockchainLockingClients;
|
|
16
17
|
private homeBlockchains;
|
|
17
18
|
private stateSigner;
|
|
18
19
|
private txSigner;
|
|
@@ -34,6 +35,12 @@ export declare class Client {
|
|
|
34
35
|
challenge(state: core.State): Promise<string>;
|
|
35
36
|
approveToken(chainId: bigint, asset: string, amount: Decimal): Promise<string>;
|
|
36
37
|
checkTokenAllowance(chainId: bigint, tokenAddress: string, owner: string): Promise<bigint>;
|
|
38
|
+
escrowSecurityTokens(targetWalletAddress: string, blockchainId: bigint, amount: Decimal): Promise<string>;
|
|
39
|
+
initiateSecurityTokensWithdrawal(blockchainId: bigint): Promise<string>;
|
|
40
|
+
cancelSecurityTokensWithdrawal(blockchainId: bigint): Promise<string>;
|
|
41
|
+
withdrawSecurityTokens(blockchainId: bigint, destinationWalletAddress: string): Promise<string>;
|
|
42
|
+
approveSecurityToken(chainId: bigint, amount: Decimal): Promise<string>;
|
|
43
|
+
getLockedBalance(chainId: bigint, wallet: string): Promise<Decimal>;
|
|
37
44
|
ping(): Promise<void>;
|
|
38
45
|
getConfig(): Promise<core.NodeConfig>;
|
|
39
46
|
getBlockchains(): Promise<core.Blockchain[]>;
|
|
@@ -50,6 +57,7 @@ export declare class Client {
|
|
|
50
57
|
transactions: core.Transaction[];
|
|
51
58
|
metadata: core.PaginationMetadata;
|
|
52
59
|
}>;
|
|
60
|
+
getActionAllowances(wallet: Address): Promise<core.ActionAllowance[]>;
|
|
53
61
|
getChannels(wallet: Address, options?: {
|
|
54
62
|
status?: string;
|
|
55
63
|
asset?: string;
|
|
@@ -73,7 +81,9 @@ export declare class Client {
|
|
|
73
81
|
metadata: core.PaginationMetadata;
|
|
74
82
|
}>;
|
|
75
83
|
getAppDefinition(appSessionId: string): Promise<app.AppDefinitionV1>;
|
|
76
|
-
createAppSession(definition: app.AppDefinitionV1, sessionData: string, quorumSigs: string[]
|
|
84
|
+
createAppSession(definition: app.AppDefinitionV1, sessionData: string, quorumSigs: string[], opts?: {
|
|
85
|
+
ownerSig?: string;
|
|
86
|
+
}): Promise<{
|
|
77
87
|
appSessionId: string;
|
|
78
88
|
version: string;
|
|
79
89
|
status: string;
|
|
@@ -81,13 +91,26 @@ export declare class Client {
|
|
|
81
91
|
submitAppSessionDeposit(appStateUpdate: app.AppStateUpdateV1, quorumSigs: string[], asset: string, depositAmount: Decimal): Promise<string>;
|
|
82
92
|
submitAppState(appStateUpdate: app.AppStateUpdateV1, quorumSigs: string[]): Promise<void>;
|
|
83
93
|
rebalanceAppSessions(signedUpdates: app.SignedAppStateUpdateV1[]): Promise<string>;
|
|
94
|
+
getApps(options?: {
|
|
95
|
+
appId?: string;
|
|
96
|
+
ownerWallet?: string;
|
|
97
|
+
page?: number;
|
|
98
|
+
pageSize?: number;
|
|
99
|
+
}): Promise<{
|
|
100
|
+
apps: AppInfoV1[];
|
|
101
|
+
metadata: core.PaginationMetadata;
|
|
102
|
+
}>;
|
|
103
|
+
registerApp(appID: string, metadata: string, creationApprovalNotRequired: boolean): Promise<void>;
|
|
84
104
|
signChannelSessionKeyState(state: ChannelSessionKeyStateV1): Promise<Hex>;
|
|
85
105
|
submitChannelSessionKeyState(state: ChannelSessionKeyStateV1): Promise<void>;
|
|
86
106
|
getLastChannelKeyStates(userAddress: string, sessionKey?: string): Promise<ChannelSessionKeyStateV1[]>;
|
|
87
107
|
signSessionKeyState(state: app.AppSessionKeyStateV1): Promise<Hex>;
|
|
88
108
|
submitSessionKeyState(state: app.AppSessionKeyStateV1): Promise<void>;
|
|
89
109
|
getLastKeyStates(userAddress: string, sessionKey?: string): Promise<app.AppSessionKeyStateV1[]>;
|
|
110
|
+
private getBlockchainRPCInfo;
|
|
111
|
+
private createEVMClients;
|
|
90
112
|
private initializeBlockchainClient;
|
|
113
|
+
private initializeLockingClient;
|
|
91
114
|
private buildSigValidatorsBitmap;
|
|
92
115
|
private getSupportedSigValidatorsBitmap;
|
|
93
116
|
private getNodeAddress;
|
package/dist/client.js
CHANGED
|
@@ -5,7 +5,7 @@ import { RPCClient } from './rpc/client';
|
|
|
5
5
|
import { WebsocketDialer } from './rpc/dialer';
|
|
6
6
|
import { ClientAssetStore } from './asset_store';
|
|
7
7
|
import { DefaultConfig } from './config';
|
|
8
|
-
import { generateNonce, transformNodeConfig, transformAssets, transformBalances, transformChannel, transformState, transformTransaction, transformPaginationMetadata, transformAppDefinitionToRPC, transformAppStateUpdateToRPC, transformSignedAppStateUpdateToRPC, transformAppSessionInfo, transformAppDefinitionFromRPC, } from './utils';
|
|
8
|
+
import { generateNonce, transformNodeConfig, transformAssets, transformBalances, transformChannel, transformState, transformTransaction, transformPaginationMetadata, transformAppDefinitionToRPC, transformAppStateUpdateToRPC, transformSignedAppStateUpdateToRPC, transformAppSessionInfo, transformAppDefinitionFromRPC, transformActionAllowance, } from './utils';
|
|
9
9
|
import * as blockchain from './blockchain';
|
|
10
10
|
import { nextState, applyChannelCreation, applyAcknowledgementTransition, applyHomeDepositTransition, applyHomeWithdrawalTransition, applyTransferSendTransition, applyFinalizeTransition, applyCommitTransition } from './core/state';
|
|
11
11
|
import { newVoidState } from './core/types';
|
|
@@ -30,6 +30,7 @@ export class Client {
|
|
|
30
30
|
this.txSigner = txSigner;
|
|
31
31
|
this.assetStore = assetStore;
|
|
32
32
|
this.blockchainClients = new Map();
|
|
33
|
+
this.blockchainLockingClients = new Map();
|
|
33
34
|
this.homeBlockchains = new Map();
|
|
34
35
|
this.exitPromise = new Promise((resolve) => {
|
|
35
36
|
this.exitResolve = resolve;
|
|
@@ -376,6 +377,30 @@ export class Client {
|
|
|
376
377
|
const blockchainClient = this.blockchainClients.get(chainId);
|
|
377
378
|
return await blockchainClient.checkAllowanceByAddress(tokenAddress, owner);
|
|
378
379
|
}
|
|
380
|
+
async escrowSecurityTokens(targetWalletAddress, blockchainId, amount) {
|
|
381
|
+
await this.initializeLockingClient(blockchainId);
|
|
382
|
+
return this.blockchainLockingClients.get(blockchainId).lock(targetWalletAddress, amount);
|
|
383
|
+
}
|
|
384
|
+
async initiateSecurityTokensWithdrawal(blockchainId) {
|
|
385
|
+
await this.initializeLockingClient(blockchainId);
|
|
386
|
+
return this.blockchainLockingClients.get(blockchainId).unlock();
|
|
387
|
+
}
|
|
388
|
+
async cancelSecurityTokensWithdrawal(blockchainId) {
|
|
389
|
+
await this.initializeLockingClient(blockchainId);
|
|
390
|
+
return this.blockchainLockingClients.get(blockchainId).relock();
|
|
391
|
+
}
|
|
392
|
+
async withdrawSecurityTokens(blockchainId, destinationWalletAddress) {
|
|
393
|
+
await this.initializeLockingClient(blockchainId);
|
|
394
|
+
return this.blockchainLockingClients.get(blockchainId).withdraw(destinationWalletAddress);
|
|
395
|
+
}
|
|
396
|
+
async approveSecurityToken(chainId, amount) {
|
|
397
|
+
await this.initializeLockingClient(chainId);
|
|
398
|
+
return this.blockchainLockingClients.get(chainId).approveToken(amount);
|
|
399
|
+
}
|
|
400
|
+
async getLockedBalance(chainId, wallet) {
|
|
401
|
+
await this.initializeLockingClient(chainId);
|
|
402
|
+
return this.blockchainLockingClients.get(chainId).getBalance(wallet);
|
|
403
|
+
}
|
|
379
404
|
async ping() {
|
|
380
405
|
await this.rpcClient.nodeV1Ping();
|
|
381
406
|
}
|
|
@@ -420,6 +445,11 @@ export class Client {
|
|
|
420
445
|
metadata: transformPaginationMetadata(resp.metadata),
|
|
421
446
|
};
|
|
422
447
|
}
|
|
448
|
+
async getActionAllowances(wallet) {
|
|
449
|
+
const req = { wallet };
|
|
450
|
+
const resp = await this.rpcClient.userV1GetActionAllowances(req);
|
|
451
|
+
return resp.allowances.map(transformActionAllowance);
|
|
452
|
+
}
|
|
423
453
|
async getChannels(wallet, options) {
|
|
424
454
|
const req = {
|
|
425
455
|
wallet,
|
|
@@ -486,12 +516,15 @@ export class Client {
|
|
|
486
516
|
const resp = await this.rpcClient.appSessionsV1GetAppDefinition(req);
|
|
487
517
|
return transformAppDefinitionFromRPC(resp.definition);
|
|
488
518
|
}
|
|
489
|
-
async createAppSession(definition, sessionData, quorumSigs) {
|
|
519
|
+
async createAppSession(definition, sessionData, quorumSigs, opts) {
|
|
490
520
|
const req = {
|
|
491
521
|
definition: transformAppDefinitionToRPC(definition),
|
|
492
522
|
session_data: sessionData,
|
|
493
523
|
quorum_sigs: quorumSigs,
|
|
494
524
|
};
|
|
525
|
+
if (opts?.ownerSig) {
|
|
526
|
+
req.owner_sig = opts.ownerSig;
|
|
527
|
+
}
|
|
495
528
|
const resp = await this.rpcClient.appSessionsV1CreateAppSession(req);
|
|
496
529
|
return {
|
|
497
530
|
appSessionId: resp.app_session_id,
|
|
@@ -530,6 +563,40 @@ export class Client {
|
|
|
530
563
|
const resp = await this.rpcClient.appSessionsV1RebalanceAppSessions(req);
|
|
531
564
|
return resp.batch_id;
|
|
532
565
|
}
|
|
566
|
+
async getApps(options) {
|
|
567
|
+
const req = {
|
|
568
|
+
app_id: options?.appId,
|
|
569
|
+
owner_wallet: options?.ownerWallet,
|
|
570
|
+
pagination: options?.page && options?.pageSize ? {
|
|
571
|
+
offset: (options.page - 1) * options.pageSize,
|
|
572
|
+
limit: options.pageSize,
|
|
573
|
+
} : undefined,
|
|
574
|
+
};
|
|
575
|
+
const resp = await this.rpcClient.appsV1GetApps(req);
|
|
576
|
+
return {
|
|
577
|
+
apps: resp.apps,
|
|
578
|
+
metadata: transformPaginationMetadata(resp.metadata),
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
async registerApp(appID, metadata, creationApprovalNotRequired) {
|
|
582
|
+
const appDef = {
|
|
583
|
+
id: appID,
|
|
584
|
+
owner_wallet: this.txSigner.getAddress(),
|
|
585
|
+
metadata,
|
|
586
|
+
version: '1',
|
|
587
|
+
creation_approval_not_required: creationApprovalNotRequired,
|
|
588
|
+
};
|
|
589
|
+
const packed = app.packAppV1(appDef);
|
|
590
|
+
if (!this.txSigner.signPersonalMessage) {
|
|
591
|
+
throw new Error('TransactionSigner must implement signPersonalMessage for app registration');
|
|
592
|
+
}
|
|
593
|
+
const ownerSig = await this.txSigner.signPersonalMessage(packed);
|
|
594
|
+
const req = {
|
|
595
|
+
app: appDef,
|
|
596
|
+
owner_sig: ownerSig,
|
|
597
|
+
};
|
|
598
|
+
await this.rpcClient.appsV1SubmitAppVersion(req);
|
|
599
|
+
}
|
|
533
600
|
async signChannelSessionKeyState(state) {
|
|
534
601
|
const metadataHash = core.getChannelSessionKeyAuthMetadataHashV1(BigInt(state.version), state.assets, BigInt(state.expires_at));
|
|
535
602
|
const packed = core.packChannelKeyStateV1(state.session_key, metadataHash);
|
|
@@ -569,10 +636,7 @@ export class Client {
|
|
|
569
636
|
const resp = await this.rpcClient.appSessionsV1GetLastKeyStates(req);
|
|
570
637
|
return resp.states;
|
|
571
638
|
}
|
|
572
|
-
async
|
|
573
|
-
if (this.blockchainClients.has(chainId)) {
|
|
574
|
-
return;
|
|
575
|
-
}
|
|
639
|
+
async getBlockchainRPCInfo(chainId) {
|
|
576
640
|
const rpcUrl = this.config.blockchainRPCs?.get(chainId);
|
|
577
641
|
if (!rpcUrl) {
|
|
578
642
|
throw new Error(`blockchain RPC not configured for chain ${chainId} (use withBlockchainRPC)`);
|
|
@@ -580,10 +644,11 @@ export class Client {
|
|
|
580
644
|
const config = await this.getConfig();
|
|
581
645
|
const blockchainInfo = config.blockchains.find((b) => b.id === chainId);
|
|
582
646
|
if (!blockchainInfo) {
|
|
583
|
-
throw new Error(`blockchain ${chainId} not
|
|
647
|
+
throw new Error(`blockchain ${chainId} not found in node config`);
|
|
584
648
|
}
|
|
585
|
-
|
|
586
|
-
|
|
649
|
+
return { rpcUrl, blockchainInfo, config };
|
|
650
|
+
}
|
|
651
|
+
createEVMClients(chainId, rpcUrl) {
|
|
587
652
|
const publicClient = createPublicClient({
|
|
588
653
|
transport: http(rpcUrl),
|
|
589
654
|
});
|
|
@@ -597,7 +662,7 @@ export class Client {
|
|
|
597
662
|
},
|
|
598
663
|
};
|
|
599
664
|
const isBrowser = typeof window !== 'undefined' && typeof window.ethereum !== 'undefined';
|
|
600
|
-
let walletClient;
|
|
665
|
+
let walletClient = null;
|
|
601
666
|
if (isBrowser) {
|
|
602
667
|
walletClient = createWalletClient({
|
|
603
668
|
chain,
|
|
@@ -606,15 +671,44 @@ export class Client {
|
|
|
606
671
|
});
|
|
607
672
|
}
|
|
608
673
|
else {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
674
|
+
const account = this.txSigner.getAccount ? this.txSigner.getAccount() : undefined;
|
|
675
|
+
if (account) {
|
|
676
|
+
walletClient = createWalletClient({
|
|
677
|
+
chain,
|
|
678
|
+
transport: http(rpcUrl),
|
|
679
|
+
account,
|
|
680
|
+
});
|
|
681
|
+
}
|
|
614
682
|
}
|
|
615
|
-
|
|
683
|
+
return { publicClient, walletClient };
|
|
684
|
+
}
|
|
685
|
+
async initializeBlockchainClient(chainId) {
|
|
686
|
+
if (this.blockchainClients.has(chainId)) {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
const { rpcUrl, blockchainInfo, config } = await this.getBlockchainRPCInfo(chainId);
|
|
690
|
+
if (!blockchainInfo.channelHubAddress) {
|
|
691
|
+
throw new Error(`channel hub address not configured for blockchain ${chainId}`);
|
|
692
|
+
}
|
|
693
|
+
const { publicClient, walletClient } = this.createEVMClients(chainId, rpcUrl);
|
|
694
|
+
if (!walletClient) {
|
|
695
|
+
throw new Error('Node.js environment requires a TransactionSigner that implements getAccount() (e.g., EthereumRawSigner)');
|
|
696
|
+
}
|
|
697
|
+
const blockchainClient = new blockchain.evm.Client(blockchainInfo.channelHubAddress, publicClient, walletClient, chainId, config.nodeAddress, this.assetStore);
|
|
616
698
|
this.blockchainClients.set(chainId, blockchainClient);
|
|
617
699
|
}
|
|
700
|
+
async initializeLockingClient(chainId) {
|
|
701
|
+
if (this.blockchainLockingClients.has(chainId)) {
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
const { rpcUrl, blockchainInfo } = await this.getBlockchainRPCInfo(chainId);
|
|
705
|
+
if (!blockchainInfo.lockingContractAddress) {
|
|
706
|
+
throw new Error(`locking contract address not configured for blockchain ${chainId}`);
|
|
707
|
+
}
|
|
708
|
+
const { publicClient, walletClient } = this.createEVMClients(chainId, rpcUrl);
|
|
709
|
+
const lockingClient = new blockchain.evm.LockingClient(blockchainInfo.lockingContractAddress, publicClient, walletClient || undefined);
|
|
710
|
+
this.blockchainLockingClients.set(chainId, lockingClient);
|
|
711
|
+
}
|
|
618
712
|
buildSigValidatorsBitmap(signerTypes) {
|
|
619
713
|
const bitmap = new Uint8Array(32);
|
|
620
714
|
for (const t of signerTypes) {
|
package/dist/core/types.d.ts
CHANGED
|
@@ -120,6 +120,7 @@ export interface Blockchain {
|
|
|
120
120
|
name: string;
|
|
121
121
|
id: bigint;
|
|
122
122
|
channelHubAddress: Address;
|
|
123
|
+
lockingContractAddress?: Address;
|
|
123
124
|
blockStep: bigint;
|
|
124
125
|
}
|
|
125
126
|
export interface Token {
|
|
@@ -154,6 +155,12 @@ export interface BalanceEntry {
|
|
|
154
155
|
asset: string;
|
|
155
156
|
balance: Decimal;
|
|
156
157
|
}
|
|
158
|
+
export interface ActionAllowance {
|
|
159
|
+
gatedAction: string;
|
|
160
|
+
timeWindow: string;
|
|
161
|
+
allowance: bigint;
|
|
162
|
+
used: bigint;
|
|
163
|
+
}
|
|
157
164
|
export interface PaginationParams {
|
|
158
165
|
offset?: number;
|
|
159
166
|
limit?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Client, DEFAULT_CHALLENGE_PERIOD, type StateSigner, type TransactionSigner } from './client';
|
|
2
|
-
export { EthereumMsgSigner, EthereumRawSigner, ChannelDefaultSigner, ChannelSessionKeyStateSigner, createSigners, } from './signers';
|
|
2
|
+
export { EthereumMsgSigner, EthereumRawSigner, ChannelDefaultSigner, ChannelSessionKeyStateSigner, AppSessionWalletSignerV1, AppSessionKeySignerV1, createSigners, } from './signers';
|
|
3
3
|
export { type Config, DefaultConfig, type Option, withHandshakeTimeout, withErrorHandler, withBlockchainRPC } from './config';
|
|
4
4
|
export { ClientAssetStore } from './asset_store';
|
|
5
5
|
export * from './utils';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Client, DEFAULT_CHALLENGE_PERIOD } from './client';
|
|
2
|
-
export { EthereumMsgSigner, EthereumRawSigner, ChannelDefaultSigner, ChannelSessionKeyStateSigner, createSigners, } from './signers';
|
|
2
|
+
export { EthereumMsgSigner, EthereumRawSigner, ChannelDefaultSigner, ChannelSessionKeyStateSigner, AppSessionWalletSignerV1, AppSessionKeySignerV1, createSigners, } from './signers';
|
|
3
3
|
export { DefaultConfig, withHandshakeTimeout, withErrorHandler, withBlockchainRPC } from './config';
|
|
4
4
|
export { ClientAssetStore } from './asset_store';
|
|
5
5
|
export * from './utils';
|
package/dist/rpc/api.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Address } from 'viem';
|
|
2
|
-
import { ChannelV1, ChannelDefinitionV1, ChannelSessionKeyStateV1, StateV1, BalanceEntryV1, TransactionV1, PaginationParamsV1, PaginationMetadataV1, AssetV1, BlockchainInfoV1 } from './types';
|
|
2
|
+
import { ChannelV1, ChannelDefinitionV1, ChannelSessionKeyStateV1, StateV1, BalanceEntryV1, TransactionV1, PaginationParamsV1, PaginationMetadataV1, AssetV1, BlockchainInfoV1, AppV1, AppInfoV1, ActionAllowanceV1 } from './types';
|
|
3
3
|
import { AppDefinitionV1, AppStateUpdateV1, AppSessionInfoV1, AppAllocationV1, AppSessionKeyStateV1, SignedAppStateUpdateV1 } from '../app/types';
|
|
4
4
|
import { TransactionType } from '../core/types';
|
|
5
5
|
export interface ChannelsV1GetHomeChannelRequest {
|
|
@@ -115,6 +115,7 @@ export interface AppSessionsV1CreateAppSessionRequest {
|
|
|
115
115
|
definition: AppDefinitionV1;
|
|
116
116
|
session_data: string;
|
|
117
117
|
quorum_sigs?: string[];
|
|
118
|
+
owner_sig?: string;
|
|
118
119
|
}
|
|
119
120
|
export interface AppSessionsV1CreateAppSessionResponse {
|
|
120
121
|
app_session_id: string;
|
|
@@ -143,6 +144,21 @@ export interface AppSessionsV1GetLastKeyStatesRequest {
|
|
|
143
144
|
export interface AppSessionsV1GetLastKeyStatesResponse {
|
|
144
145
|
states: AppSessionKeyStateV1[];
|
|
145
146
|
}
|
|
147
|
+
export interface AppsV1GetAppsRequest {
|
|
148
|
+
app_id?: string;
|
|
149
|
+
owner_wallet?: string;
|
|
150
|
+
pagination?: PaginationParamsV1;
|
|
151
|
+
}
|
|
152
|
+
export interface AppsV1GetAppsResponse {
|
|
153
|
+
apps: AppInfoV1[];
|
|
154
|
+
metadata: PaginationMetadataV1;
|
|
155
|
+
}
|
|
156
|
+
export interface AppsV1SubmitAppVersionRequest {
|
|
157
|
+
app: AppV1;
|
|
158
|
+
owner_sig: string;
|
|
159
|
+
}
|
|
160
|
+
export interface AppsV1SubmitAppVersionResponse {
|
|
161
|
+
}
|
|
146
162
|
export interface UserV1GetBalancesRequest {
|
|
147
163
|
wallet: Address;
|
|
148
164
|
}
|
|
@@ -161,6 +177,12 @@ export interface UserV1GetTransactionsResponse {
|
|
|
161
177
|
transactions: TransactionV1[];
|
|
162
178
|
metadata: PaginationMetadataV1;
|
|
163
179
|
}
|
|
180
|
+
export interface UserV1GetActionAllowancesRequest {
|
|
181
|
+
wallet: Address;
|
|
182
|
+
}
|
|
183
|
+
export interface UserV1GetActionAllowancesResponse {
|
|
184
|
+
allowances: ActionAllowanceV1[];
|
|
185
|
+
}
|
|
164
186
|
export interface NodeV1PingRequest {
|
|
165
187
|
}
|
|
166
188
|
export interface NodeV1PingResponse {
|
package/dist/rpc/client.d.ts
CHANGED
|
@@ -24,8 +24,11 @@ export declare class RPCClient {
|
|
|
24
24
|
appSessionsV1CloseAppSession(req: API.AppSessionsV1CloseAppSessionRequest, signal?: AbortSignal): Promise<API.AppSessionsV1CloseAppSessionResponse>;
|
|
25
25
|
appSessionsV1SubmitSessionKeyState(req: API.AppSessionsV1SubmitSessionKeyStateRequest, signal?: AbortSignal): Promise<API.AppSessionsV1SubmitSessionKeyStateResponse>;
|
|
26
26
|
appSessionsV1GetLastKeyStates(req: API.AppSessionsV1GetLastKeyStatesRequest, signal?: AbortSignal): Promise<API.AppSessionsV1GetLastKeyStatesResponse>;
|
|
27
|
+
appsV1GetApps(req: API.AppsV1GetAppsRequest, signal?: AbortSignal): Promise<API.AppsV1GetAppsResponse>;
|
|
28
|
+
appsV1SubmitAppVersion(req: API.AppsV1SubmitAppVersionRequest, signal?: AbortSignal): Promise<API.AppsV1SubmitAppVersionResponse>;
|
|
27
29
|
userV1GetBalances(req: API.UserV1GetBalancesRequest, signal?: AbortSignal): Promise<API.UserV1GetBalancesResponse>;
|
|
28
30
|
userV1GetTransactions(req: API.UserV1GetTransactionsRequest, signal?: AbortSignal): Promise<API.UserV1GetTransactionsResponse>;
|
|
31
|
+
userV1GetActionAllowances(req: API.UserV1GetActionAllowancesRequest, signal?: AbortSignal): Promise<API.UserV1GetActionAllowancesResponse>;
|
|
29
32
|
nodeV1Ping(signal?: AbortSignal): Promise<void>;
|
|
30
33
|
nodeV1GetConfig(signal?: AbortSignal): Promise<API.NodeV1GetConfigResponse>;
|
|
31
34
|
nodeV1GetAssets(req: API.NodeV1GetAssetsRequest, signal?: AbortSignal): Promise<API.NodeV1GetAssetsResponse>;
|
package/dist/rpc/client.js
CHANGED
|
@@ -72,12 +72,21 @@ export class RPCClient {
|
|
|
72
72
|
async appSessionsV1GetLastKeyStates(req, signal) {
|
|
73
73
|
return this.call(Methods.AppSessionsV1GetLastKeyStatesMethod, req, signal);
|
|
74
74
|
}
|
|
75
|
+
async appsV1GetApps(req, signal) {
|
|
76
|
+
return this.call(Methods.AppsV1GetAppsMethod, req, signal);
|
|
77
|
+
}
|
|
78
|
+
async appsV1SubmitAppVersion(req, signal) {
|
|
79
|
+
return this.call(Methods.AppsV1SubmitAppVersionMethod, req, signal);
|
|
80
|
+
}
|
|
75
81
|
async userV1GetBalances(req, signal) {
|
|
76
82
|
return this.call(Methods.UserV1GetBalancesMethod, req, signal);
|
|
77
83
|
}
|
|
78
84
|
async userV1GetTransactions(req, signal) {
|
|
79
85
|
return this.call(Methods.UserV1GetTransactionsMethod, req, signal);
|
|
80
86
|
}
|
|
87
|
+
async userV1GetActionAllowances(req, signal) {
|
|
88
|
+
return this.call(Methods.UserV1GetActionAllowancesMethod, req, signal);
|
|
89
|
+
}
|
|
81
90
|
async nodeV1Ping(signal) {
|
|
82
91
|
await this.call(Methods.NodeV1PingMethod, {}, signal);
|
|
83
92
|
}
|
package/dist/rpc/methods.d.ts
CHANGED
|
@@ -20,9 +20,13 @@ export declare const AppSessionsV1CreateAppSessionMethod: Method;
|
|
|
20
20
|
export declare const AppSessionsV1CloseAppSessionMethod: Method;
|
|
21
21
|
export declare const AppSessionsV1SubmitSessionKeyStateMethod: Method;
|
|
22
22
|
export declare const AppSessionsV1GetLastKeyStatesMethod: Method;
|
|
23
|
+
export declare const AppsV1Group: Group;
|
|
24
|
+
export declare const AppsV1GetAppsMethod: Method;
|
|
25
|
+
export declare const AppsV1SubmitAppVersionMethod: Method;
|
|
23
26
|
export declare const UserV1Group: Group;
|
|
24
27
|
export declare const UserV1GetBalancesMethod: Method;
|
|
25
28
|
export declare const UserV1GetTransactionsMethod: Method;
|
|
29
|
+
export declare const UserV1GetActionAllowancesMethod: Method;
|
|
26
30
|
export declare const NodeV1Group: Group;
|
|
27
31
|
export declare const NodeV1PingMethod: Method;
|
|
28
32
|
export declare const NodeV1GetConfigMethod: Method;
|
package/dist/rpc/methods.js
CHANGED
|
@@ -18,9 +18,13 @@ export const AppSessionsV1CreateAppSessionMethod = 'app_sessions.v1.create_app_s
|
|
|
18
18
|
export const AppSessionsV1CloseAppSessionMethod = 'app_sessions.v1.close_app_session';
|
|
19
19
|
export const AppSessionsV1SubmitSessionKeyStateMethod = 'app_sessions.v1.submit_session_key_state';
|
|
20
20
|
export const AppSessionsV1GetLastKeyStatesMethod = 'app_sessions.v1.get_last_key_states';
|
|
21
|
+
export const AppsV1Group = 'apps.v1';
|
|
22
|
+
export const AppsV1GetAppsMethod = 'apps.v1.get_apps';
|
|
23
|
+
export const AppsV1SubmitAppVersionMethod = 'apps.v1.submit_app_version';
|
|
21
24
|
export const UserV1Group = 'user.v1';
|
|
22
25
|
export const UserV1GetBalancesMethod = 'user.v1.get_balances';
|
|
23
26
|
export const UserV1GetTransactionsMethod = 'user.v1.get_transactions';
|
|
27
|
+
export const UserV1GetActionAllowancesMethod = 'user.v1.get_action_allowances';
|
|
24
28
|
export const NodeV1Group = 'node.v1';
|
|
25
29
|
export const NodeV1PingMethod = 'node.v1.ping';
|
|
26
30
|
export const NodeV1GetConfigMethod = 'node.v1.get_config';
|
package/dist/rpc/types.d.ts
CHANGED
|
@@ -55,6 +55,17 @@ export interface ChannelSessionKeyStateV1 {
|
|
|
55
55
|
expires_at: string;
|
|
56
56
|
user_sig: string;
|
|
57
57
|
}
|
|
58
|
+
export interface AppV1 {
|
|
59
|
+
id: string;
|
|
60
|
+
owner_wallet: string;
|
|
61
|
+
metadata: string;
|
|
62
|
+
version: string;
|
|
63
|
+
creation_approval_not_required: boolean;
|
|
64
|
+
}
|
|
65
|
+
export interface AppInfoV1 extends AppV1 {
|
|
66
|
+
created_at: string;
|
|
67
|
+
updated_at: string;
|
|
68
|
+
}
|
|
58
69
|
export interface AssetV1 {
|
|
59
70
|
name: string;
|
|
60
71
|
symbol: string;
|
|
@@ -73,6 +84,7 @@ export interface BlockchainInfoV1 {
|
|
|
73
84
|
name: string;
|
|
74
85
|
blockchain_id: string;
|
|
75
86
|
channel_hub_address: Address;
|
|
87
|
+
locking_contract_address?: Address;
|
|
76
88
|
}
|
|
77
89
|
export interface BalanceEntryV1 {
|
|
78
90
|
asset: string;
|
|
@@ -93,6 +105,12 @@ export interface PaginationParamsV1 {
|
|
|
93
105
|
offset?: number;
|
|
94
106
|
limit?: number;
|
|
95
107
|
}
|
|
108
|
+
export interface ActionAllowanceV1 {
|
|
109
|
+
gated_action: string;
|
|
110
|
+
time_window: string;
|
|
111
|
+
allowance: string;
|
|
112
|
+
used: string;
|
|
113
|
+
}
|
|
96
114
|
export interface PaginationMetadataV1 {
|
|
97
115
|
page: number;
|
|
98
116
|
per_page: number;
|
package/dist/signers.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export interface TransactionSigner {
|
|
|
10
10
|
signMessage(message: {
|
|
11
11
|
raw: Hex;
|
|
12
12
|
}): Promise<Hex>;
|
|
13
|
+
signPersonalMessage?(hash: Hex): Promise<Hex>;
|
|
14
|
+
getAccount?(): ReturnType<typeof privateKeyToAccount>;
|
|
13
15
|
}
|
|
14
16
|
export declare class EthereumMsgSigner implements StateSigner {
|
|
15
17
|
private account;
|
|
@@ -25,6 +27,8 @@ export declare class EthereumRawSigner implements TransactionSigner {
|
|
|
25
27
|
signMessage(message: {
|
|
26
28
|
raw: Hex;
|
|
27
29
|
}): Promise<Hex>;
|
|
30
|
+
signPersonalMessage(hash: Hex): Promise<Hex>;
|
|
31
|
+
getAccount(): ReturnType<typeof privateKeyToAccount>;
|
|
28
32
|
}
|
|
29
33
|
export declare class ChannelDefaultSigner implements StateSigner {
|
|
30
34
|
private inner;
|
|
@@ -42,6 +46,18 @@ export declare class ChannelSessionKeyStateSigner implements StateSigner {
|
|
|
42
46
|
getSessionKeyAddress(): Address;
|
|
43
47
|
signMessage(hash: Hex): Promise<Hex>;
|
|
44
48
|
}
|
|
49
|
+
export declare class AppSessionWalletSignerV1 implements StateSigner {
|
|
50
|
+
private inner;
|
|
51
|
+
constructor(inner: StateSigner);
|
|
52
|
+
getAddress(): Address;
|
|
53
|
+
signMessage(hash: Hex): Promise<Hex>;
|
|
54
|
+
}
|
|
55
|
+
export declare class AppSessionKeySignerV1 implements StateSigner {
|
|
56
|
+
private inner;
|
|
57
|
+
constructor(inner: StateSigner);
|
|
58
|
+
getAddress(): Address;
|
|
59
|
+
signMessage(hash: Hex): Promise<Hex>;
|
|
60
|
+
}
|
|
45
61
|
export declare function createSigners(privateKey: Hex): {
|
|
46
62
|
stateSigner: StateSigner;
|
|
47
63
|
txSigner: TransactionSigner;
|
package/dist/signers.js
CHANGED
|
@@ -36,6 +36,12 @@ export class EthereumRawSigner {
|
|
|
36
36
|
async signMessage(message) {
|
|
37
37
|
return await this.account.sign({ hash: message.raw });
|
|
38
38
|
}
|
|
39
|
+
async signPersonalMessage(hash) {
|
|
40
|
+
return await this.account.signMessage({ message: { raw: hash } });
|
|
41
|
+
}
|
|
42
|
+
getAccount() {
|
|
43
|
+
return this.account;
|
|
44
|
+
}
|
|
39
45
|
}
|
|
40
46
|
export class ChannelDefaultSigner {
|
|
41
47
|
constructor(inner) {
|
|
@@ -87,6 +93,30 @@ export class ChannelSessionKeyStateSigner {
|
|
|
87
93
|
return `0x01${encoded.slice(2)}`;
|
|
88
94
|
}
|
|
89
95
|
}
|
|
96
|
+
export class AppSessionWalletSignerV1 {
|
|
97
|
+
constructor(inner) {
|
|
98
|
+
this.inner = inner;
|
|
99
|
+
}
|
|
100
|
+
getAddress() {
|
|
101
|
+
return this.inner.getAddress();
|
|
102
|
+
}
|
|
103
|
+
async signMessage(hash) {
|
|
104
|
+
const sig = await this.inner.signMessage(hash);
|
|
105
|
+
return `0xa1${sig.slice(2)}`;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export class AppSessionKeySignerV1 {
|
|
109
|
+
constructor(inner) {
|
|
110
|
+
this.inner = inner;
|
|
111
|
+
}
|
|
112
|
+
getAddress() {
|
|
113
|
+
return this.inner.getAddress();
|
|
114
|
+
}
|
|
115
|
+
async signMessage(hash) {
|
|
116
|
+
const sig = await this.inner.signMessage(hash);
|
|
117
|
+
return `0xa2${sig.slice(2)}`;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
90
120
|
export function createSigners(privateKey) {
|
|
91
121
|
const account = privateKeyToAccount(privateKey);
|
|
92
122
|
return {
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as core from './core/types';
|
|
2
2
|
import * as API from './rpc/api';
|
|
3
|
-
import { AssetV1, BalanceEntryV1, ChannelV1, LedgerV1, TransitionV1, StateV1, TransactionV1, PaginationMetadataV1 } from './rpc/types';
|
|
3
|
+
import { AssetV1, BalanceEntryV1, ChannelV1, LedgerV1, TransitionV1, StateV1, TransactionV1, PaginationMetadataV1, ActionAllowanceV1 } from './rpc/types';
|
|
4
4
|
export declare function generateNonce(): bigint;
|
|
5
5
|
export declare function transformNodeConfig(resp: API.NodeV1GetConfigResponse): core.NodeConfig;
|
|
6
6
|
export declare function transformAssets(assets: AssetV1[]): core.Asset[];
|
|
@@ -11,6 +11,7 @@ export declare function transformTransition(transition: TransitionV1): core.Tran
|
|
|
11
11
|
export declare function transformState(state: StateV1): core.State;
|
|
12
12
|
export declare function transformTransaction(tx: TransactionV1): core.Transaction;
|
|
13
13
|
export declare function transformPaginationMetadata(metadata: PaginationMetadataV1): core.PaginationMetadata;
|
|
14
|
+
export declare function transformActionAllowance(a: ActionAllowanceV1): core.ActionAllowance;
|
|
14
15
|
import { AppDefinitionV1, AppStateUpdateV1, SignedAppStateUpdateV1, AppSessionInfoV1 } from './app/types';
|
|
15
16
|
export declare function transformAppDefinitionToRPC(def: AppDefinitionV1): any;
|
|
16
17
|
export declare function transformAppStateUpdateToRPC(update: AppStateUpdateV1): {
|
package/dist/utils.js
CHANGED
|
@@ -17,6 +17,7 @@ export function transformNodeConfig(resp) {
|
|
|
17
17
|
name: info.name,
|
|
18
18
|
id: BigInt(info.blockchain_id),
|
|
19
19
|
channelHubAddress: info.channel_hub_address,
|
|
20
|
+
lockingContractAddress: info.locking_contract_address,
|
|
20
21
|
blockStep: 0n,
|
|
21
22
|
}));
|
|
22
23
|
return {
|
|
@@ -164,9 +165,17 @@ export function transformPaginationMetadata(metadata) {
|
|
|
164
165
|
pageCount: metadata.page_count,
|
|
165
166
|
};
|
|
166
167
|
}
|
|
168
|
+
export function transformActionAllowance(a) {
|
|
169
|
+
return {
|
|
170
|
+
gatedAction: a.gated_action,
|
|
171
|
+
timeWindow: a.time_window,
|
|
172
|
+
allowance: BigInt(a.allowance),
|
|
173
|
+
used: BigInt(a.used),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
167
176
|
export function transformAppDefinitionToRPC(def) {
|
|
168
177
|
return {
|
|
169
|
-
|
|
178
|
+
application_id: def.applicationId,
|
|
170
179
|
participants: def.participants.map(p => ({
|
|
171
180
|
wallet_address: p.walletAddress,
|
|
172
181
|
signature_weight: p.signatureWeight,
|
|
@@ -197,15 +206,10 @@ export function transformSignedAppStateUpdateToRPC(signed) {
|
|
|
197
206
|
export function transformAppSessionInfo(raw) {
|
|
198
207
|
return {
|
|
199
208
|
appSessionId: raw.app_session_id,
|
|
209
|
+
appDefinition: transformAppDefinitionFromRPC(raw.app_definition),
|
|
200
210
|
isClosed: raw.status === 'closed',
|
|
201
|
-
participants: (raw.participants || []).map((p) => ({
|
|
202
|
-
walletAddress: p.wallet_address,
|
|
203
|
-
signatureWeight: p.signature_weight,
|
|
204
|
-
})),
|
|
205
211
|
sessionData: raw.session_data || '',
|
|
206
|
-
quorum: raw.quorum,
|
|
207
212
|
version: BigInt(raw.version),
|
|
208
|
-
nonce: BigInt(raw.nonce),
|
|
209
213
|
allocations: (raw.allocations || []).map((a) => ({
|
|
210
214
|
participant: a.participant,
|
|
211
215
|
asset: a.asset,
|
|
@@ -214,8 +218,11 @@ export function transformAppSessionInfo(raw) {
|
|
|
214
218
|
};
|
|
215
219
|
}
|
|
216
220
|
export function transformAppDefinitionFromRPC(raw) {
|
|
221
|
+
if (!raw.application_id || raw.nonce === undefined || raw.nonce === null) {
|
|
222
|
+
throw new Error('Invalid app definition: missing required fields (application_id, nonce)');
|
|
223
|
+
}
|
|
217
224
|
return {
|
|
218
|
-
|
|
225
|
+
applicationId: raw.application_id,
|
|
219
226
|
participants: (raw.participants || []).map((p) => ({
|
|
220
227
|
walletAddress: p.wallet_address,
|
|
221
228
|
signatureWeight: p.signature_weight,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yellow-org/sdk",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "The
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "The Yellow SDK empowers developers to build high-performance, scalable web3 applications using state channels. It's designed to provide near-instant transactions and significantly improved user experiences by minimizing direct blockchain interactions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -34,7 +34,6 @@
|
|
|
34
34
|
"prepublishOnly": "npm run clean && npm run build:prod"
|
|
35
35
|
},
|
|
36
36
|
"keywords": [
|
|
37
|
-
"erc7824",
|
|
38
37
|
"yellow",
|
|
39
38
|
"yellow-org",
|
|
40
39
|
"statechannels",
|
|
@@ -53,7 +52,7 @@
|
|
|
53
52
|
"license": "MIT",
|
|
54
53
|
"repository": {
|
|
55
54
|
"type": "git",
|
|
56
|
-
"url": "https://github.com/
|
|
55
|
+
"url": "https://github.com/layer-3/nitrolite.git"
|
|
57
56
|
},
|
|
58
57
|
"engines": {
|
|
59
58
|
"node": ">=20.0.0"
|