jalin-sdk 0.1.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/LICENSE +21 -0
- package/README.md +81 -0
- package/dist/anonymity.d.ts +99 -0
- package/dist/anonymity.d.ts.map +1 -0
- package/dist/anonymity.js +166 -0
- package/dist/anonymity.js.map +1 -0
- package/dist/crowd.d.ts +53 -0
- package/dist/crowd.d.ts.map +1 -0
- package/dist/crowd.js +50 -0
- package/dist/crowd.js.map +1 -0
- package/dist/disclosure.d.ts +22 -0
- package/dist/disclosure.d.ts.map +1 -0
- package/dist/disclosure.js +98 -0
- package/dist/disclosure.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/plan.d.ts +88 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +161 -0
- package/dist/plan.js.map +1 -0
- package/dist/receipt.d.ts +77 -0
- package/dist/receipt.d.ts.map +1 -0
- package/dist/receipt.js +164 -0
- package/dist/receipt.js.map +1 -0
- package/dist/recipes.d.ts +60 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/recipes.js +57 -0
- package/dist/recipes.js.map +1 -0
- package/dist/rpc-response.d.ts +22 -0
- package/dist/rpc-response.d.ts.map +1 -0
- package/dist/rpc-response.js +44 -0
- package/dist/rpc-response.js.map +1 -0
- package/dist/shadow.d.ts +72 -0
- package/dist/shadow.d.ts.map +1 -0
- package/dist/shadow.js +61 -0
- package/dist/shadow.js.map +1 -0
- package/dist/share.d.ts +46 -0
- package/dist/share.d.ts.map +1 -0
- package/dist/share.js +99 -0
- package/dist/share.js.map +1 -0
- package/dist/subaccounts.d.ts +63 -0
- package/dist/subaccounts.d.ts.map +1 -0
- package/dist/subaccounts.js +83 -0
- package/dist/subaccounts.js.map +1 -0
- package/dist/wallet.d.ts +103 -0
- package/dist/wallet.d.ts.map +1 -0
- package/dist/wallet.js +135 -0
- package/dist/wallet.js.map +1 -0
- package/package.json +36 -0
package/dist/wallet.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turning a plan into STRK20 wallet actions.
|
|
3
|
+
*
|
|
4
|
+
* This is the part that is easy to get subtly wrong. Three rules, none of them
|
|
5
|
+
* obvious from the plan on its own:
|
|
6
|
+
*
|
|
7
|
+
* 1. The pool has to be told to fund the router. That is a `withdraw` action with
|
|
8
|
+
* the router as recipient - a plain public transfer, which is why the phase
|
|
9
|
+
* order is withdraw before invoke.
|
|
10
|
+
* 2. `${openNoteIds[N]}` means "the Nth transfer action with amount OPEN", not
|
|
11
|
+
* "the Nth output". They are the same thing only if the OPEN transfers are
|
|
12
|
+
* emitted in output order, which is what this module guarantees.
|
|
13
|
+
* 3. One invoke per pool transaction. A plan is one invoke no matter how many
|
|
14
|
+
* steps it has; that is the entire reason the router exists.
|
|
15
|
+
*/
|
|
16
|
+
import { encodePlan, openNote } from "./plan.js";
|
|
17
|
+
/** `${openNoteIds[N]}` or `${poolAddress}` - resolved by the wallet, not by us. */
|
|
18
|
+
const PLACEHOLDER = /^\$\{(?:openNoteIds\[[0-9]+\]|poolAddress)\}$/;
|
|
19
|
+
/**
|
|
20
|
+
* One felt, canonically encoded for the wallet.
|
|
21
|
+
*
|
|
22
|
+
* Two things are being fixed here, and both fail the same way. JSON has no
|
|
23
|
+
* bigint, so `JSON.stringify` throws on one rather than coercing it. And a felt
|
|
24
|
+
* written with leading zeros - `0x0471…` for `0x471…` - is *non-canonical*: it
|
|
25
|
+
* parses to the same number and is not the same string, and the STRK20 stack
|
|
26
|
+
* treats non-canonically encoded addresses as a distinct case rather than
|
|
27
|
+
* normalising them for you.
|
|
28
|
+
*
|
|
29
|
+
* Placeholders pass through untouched. Normalising one would destroy it.
|
|
30
|
+
*/
|
|
31
|
+
export function toFelt(felt) {
|
|
32
|
+
// The regex proves the shape; TypeScript cannot read a regex, so this is the
|
|
33
|
+
// one place the two have to be trusted to agree. Both are right here, and
|
|
34
|
+
// both are tested.
|
|
35
|
+
if (typeof felt === 'string' && PLACEHOLDER.test(felt))
|
|
36
|
+
return felt;
|
|
37
|
+
return `0x${BigInt(felt).toString(16)}`;
|
|
38
|
+
}
|
|
39
|
+
export function feltsToStrings(felts) {
|
|
40
|
+
return felts.map(toFelt);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Rejects a plan whose note ids are not `openNote(0..n-1)` in order.
|
|
44
|
+
*
|
|
45
|
+
* Getting this wrong does not fail loudly: the wallet resolves the placeholder to
|
|
46
|
+
* a real note id, the router credits a real amount, and the value lands in the
|
|
47
|
+
* wrong note. Better to refuse to build the transaction.
|
|
48
|
+
*/
|
|
49
|
+
function assertNoteIdsAreInOrder(plan) {
|
|
50
|
+
plan.outputs.forEach((output, index) => {
|
|
51
|
+
const expected = openNote(index);
|
|
52
|
+
if (output.noteId !== expected) {
|
|
53
|
+
throw new Error(`output ${index} carries note id ${String(output.noteId)}, expected ${expected}. ` +
|
|
54
|
+
'Open notes are numbered by the order of the OPEN transfer actions, so output N must use openNote(N).');
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
export function toWalletActions(plan, args) {
|
|
59
|
+
assertNoteIdsAreInOrder(plan);
|
|
60
|
+
if (args.inputs.length === 0 && plan.steps.some((s) => s.approvals.length > 0)) {
|
|
61
|
+
throw new Error('this plan approves tokens it was never funded with; add the inputs the pool should withdraw to the router');
|
|
62
|
+
}
|
|
63
|
+
const actions = [];
|
|
64
|
+
// 1. Fund the router. Public, and visible as the pool paying the router.
|
|
65
|
+
//
|
|
66
|
+
// There is no deposit action here, and that is a finding rather than an
|
|
67
|
+
// omission. Shielding in the same transaction that spends the note is the
|
|
68
|
+
// obvious way to onboard somebody in one step, and it does not work: mainnet
|
|
69
|
+
// answers INSUFFICIENT_PRIVATE_BALANCE. Across the pool's whole life - 342
|
|
70
|
+
// transactions carrying a Deposit and 247 carrying an invoke - not one
|
|
71
|
+
// carries both. Shield in one transaction, spend in the next.
|
|
72
|
+
for (const input of args.inputs) {
|
|
73
|
+
actions.push({
|
|
74
|
+
type: 'withdraw',
|
|
75
|
+
token: toFelt(input.token),
|
|
76
|
+
amount: toFelt(input.amount),
|
|
77
|
+
recipient: toFelt(args.router),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// 2. One open note per output, in output order. This is what numbers them.
|
|
81
|
+
for (const output of plan.outputs) {
|
|
82
|
+
actions.push({
|
|
83
|
+
type: 'transfer',
|
|
84
|
+
token: toFelt(output.token),
|
|
85
|
+
amount: 'OPEN',
|
|
86
|
+
recipient: toFelt(args.recipient),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// 3. The plan itself, as the single permitted invoke.
|
|
90
|
+
actions.push({
|
|
91
|
+
type: 'invoke',
|
|
92
|
+
contract: toFelt(args.router),
|
|
93
|
+
calldata: feltsToStrings(encodePlan(plan)),
|
|
94
|
+
});
|
|
95
|
+
return actions;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The same plan, for the SDK route rather than the wallet route.
|
|
99
|
+
*
|
|
100
|
+
* The two routes differ in one place that is easy to miss: a wallet resolves
|
|
101
|
+
* `${openNoteIds[N]}` itself, while the SDK hands you the real note ids in the
|
|
102
|
+
* `invoke` callback and expects them substituted before encoding. Passing a
|
|
103
|
+
* placeholder string here would be encoded as a literal and the pool would
|
|
104
|
+
* credit nothing.
|
|
105
|
+
*
|
|
106
|
+
* Returns starknet.js `CallDetails`. The entry point is implied - the pool calls
|
|
107
|
+
* the helper through its own `INVOKE_SELECTOR`, not through a name.
|
|
108
|
+
*/
|
|
109
|
+
export function toInvokeCall(plan, args) {
|
|
110
|
+
if (plan.outputs.length !== args.openNotes.length) {
|
|
111
|
+
throw new Error(`plan declares ${plan.outputs.length} outputs but the pool opened ${args.openNotes.length} notes; they are matched by position`);
|
|
112
|
+
}
|
|
113
|
+
const resolved = {
|
|
114
|
+
steps: plan.steps,
|
|
115
|
+
outputs: plan.outputs.map((output, index) => {
|
|
116
|
+
const note = args.openNotes[index];
|
|
117
|
+
if (BigInt(note.token) !== BigInt(output.token)) {
|
|
118
|
+
throw new Error(`output ${index} is for token ${String(output.token)} but open note ${index} is for ${String(note.token)}`);
|
|
119
|
+
}
|
|
120
|
+
return { ...output, noteId: note.noteId };
|
|
121
|
+
}),
|
|
122
|
+
};
|
|
123
|
+
return {
|
|
124
|
+
contractAddress: args.router,
|
|
125
|
+
calldata: encodePlan(resolved, args.poolAddress),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The felts a wallet will actually see, with placeholders left as strings.
|
|
130
|
+
* Useful for showing a user what they are about to sign.
|
|
131
|
+
*/
|
|
132
|
+
export function previewCalldata(plan, poolAddress) {
|
|
133
|
+
return encodePlan(plan, poolAddress).map((felt) => typeof felt === 'bigint' ? `0x${felt.toString(16)}` : felt);
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=wallet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet.js","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAwB,MAAM,WAAW,CAAA;AAqBtE,mFAAmF;AACnF,MAAM,WAAW,GAAG,+CAA+C,CAAA;AAEnE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAC,IAAqB;IAC1C,6EAA6E;IAC7E,0EAA0E;IAC1E,mBAAmB;IACnB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAgB,CAAA;IAC/E,OAAO,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAA;AACzC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAA0B;IACvD,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AAC1B,CAAC;AAWD;;;;;;GAMG;AACH,SAAS,uBAAuB,CAAC,IAAU;IACzC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QACrC,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;QAChC,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,UAAU,KAAK,oBAAoB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,QAAQ,IAAI;gBAChF,sGAAsG,CACzG,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAU,EAAE,IAAsB;IAChE,uBAAuB,CAAC,IAAI,CAAC,CAAA;IAE7B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QAC/E,MAAM,IAAI,KAAK,CACb,2GAA2G,CAC5G,CAAA;IACH,CAAC;IAED,MAAM,OAAO,GAAmB,EAAE,CAAA;IAElC,yEAAyE;IACzE,EAAE;IACF,wEAAwE;IACxE,0EAA0E;IAC1E,6EAA6E;IAC7E,2EAA2E;IAC3E,uEAAuE;IACvE,8DAA8D;IAC9D,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;YAC1B,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;YAC5B,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;SAC/B,CAAC,CAAA;IACJ,CAAC;IAED,2EAA2E;IAC3E,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;YAC3B,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;SAClC,CAAC,CAAA;IACJ,CAAC;IAED,sDAAsD;IACtD,OAAO,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7B,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;KAC3C,CAAC,CAAA;IAEF,OAAO,OAAO,CAAA;AAChB,CAAC;AAQD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAU,EACV,IAA6E;IAE7E,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CACb,iBAAiB,IAAI,CAAC,OAAO,CAAC,MAAM,gCAAgC,IAAI,CAAC,SAAS,CAAC,MAAM,sCAAsC,CAChI,CAAA;IACH,CAAC;IAED,MAAM,QAAQ,GAAS;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAE,CAAA;YACnC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChD,MAAM,IAAI,KAAK,CACb,UAAU,KAAK,iBAAiB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,KAAK,WAAW,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAC3G,CAAA;YACH,CAAC;YACD,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAA;QAC3C,CAAC,CAAC;KACH,CAAA;IAED,OAAO;QACL,eAAe,EAAE,IAAI,CAAC,MAAM;QAC5B,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;KACjD,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAAU,EAAE,WAAkB;IAC5D,OAAO,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAChD,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAC3D,CAAA;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jalin-sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Plan encoding and sub-account portfolio helpers for the Jalin router on STRK20",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"starknet",
|
|
9
|
+
"strk20",
|
|
10
|
+
"privacy",
|
|
11
|
+
"cairo",
|
|
12
|
+
"defi",
|
|
13
|
+
"shielded-pool"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/PugarHuda/jalin#readme",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/PugarHuda/jalin.git",
|
|
19
|
+
"directory": "sdk"
|
|
20
|
+
},
|
|
21
|
+
"bugs": "https://github.com/PugarHuda/jalin/issues",
|
|
22
|
+
"main": "./dist/index.js",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"types": "./dist/index.d.ts"
|
|
36
|
+
}
|