@fivenorth/loop-sdk 0.5.1 → 0.6.1
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 +32 -1
- package/dist/index.js +100 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -90,6 +90,8 @@ const holdings = await provider.getHolding();
|
|
|
90
90
|
console.log(holdings);
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
Each holding includes its `instrument_id` (with `admin` and `id` fields), which you can use when building transfers for CC, CIP-56 tokens, LOOP, or any custom instrument.
|
|
94
|
+
|
|
93
95
|
#### Get Active Contracts
|
|
94
96
|
|
|
95
97
|
You can query for active contracts by `templateId` or `interfaceId`.
|
|
@@ -151,6 +153,35 @@ try {
|
|
|
151
153
|
}
|
|
152
154
|
```
|
|
153
155
|
|
|
156
|
+
#### Transfer (built-in helper)
|
|
157
|
+
|
|
158
|
+
```javascript
|
|
159
|
+
await loop.wallet.transfer(
|
|
160
|
+
'receiver::fingerprint',
|
|
161
|
+
'5', // amount (string or number)
|
|
162
|
+
{
|
|
163
|
+
// Optional overrides. Defaults to Amulet/DSO if omitted.
|
|
164
|
+
instrument_admin: 'issuer::fingerprint', // optional
|
|
165
|
+
instrument_id: 'Amulet', // optional
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
requestedAt: new Date().toISOString(), // optional
|
|
169
|
+
executeBefore: new Date(Date.now() + 24*60*60*1000).toISOString(), // optional
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Notes:
|
|
175
|
+
- You must have spendable holdings for the specified instrument (admin + id). If left blank, the SDK defaults to the native token.
|
|
176
|
+
- The helper handles fetching holdings, building the transfer factory payload, and submitting via Wallet Connect.
|
|
177
|
+
|
|
178
|
+
Common instrument overrides (pass into the `instrument` argument above):
|
|
179
|
+
|
|
180
|
+
- Canton Coin (CC): `{ instrument_admin: 'cc-issuer::fingerprint', instrument_id: 'CC' }`
|
|
181
|
+
- CIP-56: `{ instrument_admin: 'cip56-issuer::fingerprint', instrument_id: 'CIP-56' }`
|
|
182
|
+
|
|
183
|
+
Swap in the admin/id for the specific instrument you hold in the Loop wallet.
|
|
184
|
+
|
|
154
185
|
# API
|
|
155
186
|
|
|
156
187
|
Coming soon
|
|
@@ -179,4 +210,4 @@ Upon doing so you can visit http://localhost:3030/ to see the local demo app, se
|
|
|
179
210
|
```
|
|
180
211
|
bun run build
|
|
181
212
|
bun publish
|
|
182
|
-
```
|
|
213
|
+
```
|
package/dist/index.js
CHANGED
|
@@ -2153,6 +2153,39 @@ class Connection {
|
|
|
2153
2153
|
}
|
|
2154
2154
|
return response.json();
|
|
2155
2155
|
}
|
|
2156
|
+
async prepareTransfer(authToken, params) {
|
|
2157
|
+
const payload = {
|
|
2158
|
+
recipient: params.recipient,
|
|
2159
|
+
amount: params.amount
|
|
2160
|
+
};
|
|
2161
|
+
if (params.instrument) {
|
|
2162
|
+
if (params.instrument.instrument_admin) {
|
|
2163
|
+
payload.instrument_admin = params.instrument.instrument_admin;
|
|
2164
|
+
}
|
|
2165
|
+
if (params.instrument.instrument_id) {
|
|
2166
|
+
payload.instrument_id = params.instrument.instrument_id;
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
if (params.requested_at) {
|
|
2170
|
+
payload.requested_at = params.requested_at;
|
|
2171
|
+
}
|
|
2172
|
+
if (params.execute_before) {
|
|
2173
|
+
payload.execute_before = params.execute_before;
|
|
2174
|
+
}
|
|
2175
|
+
const response = await fetch(`${this.apiUrl}/api/v1/.connect/pair/transfer`, {
|
|
2176
|
+
method: "POST",
|
|
2177
|
+
headers: {
|
|
2178
|
+
"Content-Type": "application/json",
|
|
2179
|
+
Authorization: `Bearer ${authToken}`
|
|
2180
|
+
},
|
|
2181
|
+
body: JSON.stringify(payload)
|
|
2182
|
+
});
|
|
2183
|
+
if (!response.ok) {
|
|
2184
|
+
throw new Error("Failed to prepare transfer.");
|
|
2185
|
+
}
|
|
2186
|
+
const data = await response.json();
|
|
2187
|
+
return data.payload;
|
|
2188
|
+
}
|
|
2156
2189
|
async verifySession(authToken) {
|
|
2157
2190
|
const response = await fetch(`${this.apiUrl}/api/v1/.connect/pair/account`, {
|
|
2158
2191
|
method: "GET",
|
|
@@ -2235,7 +2268,7 @@ class Provider {
|
|
|
2235
2268
|
email;
|
|
2236
2269
|
auth_token;
|
|
2237
2270
|
requests = new Map;
|
|
2238
|
-
requestTimeout =
|
|
2271
|
+
requestTimeout = 300000;
|
|
2239
2272
|
constructor({ connection, party_id, public_key, auth_token, email, requestTimeout }) {
|
|
2240
2273
|
if (!connection) {
|
|
2241
2274
|
throw new Error("Provider requires a connection object.");
|
|
@@ -2245,7 +2278,7 @@ class Provider {
|
|
|
2245
2278
|
this.public_key = public_key;
|
|
2246
2279
|
this.email = email;
|
|
2247
2280
|
this.auth_token = auth_token;
|
|
2248
|
-
this.requestTimeout = requestTimeout ||
|
|
2281
|
+
this.requestTimeout = requestTimeout || 300000;
|
|
2249
2282
|
}
|
|
2250
2283
|
handleResponse(message) {
|
|
2251
2284
|
console.log("Received response:", message);
|
|
@@ -2262,6 +2295,42 @@ class Provider {
|
|
|
2262
2295
|
async submitTransaction(payload) {
|
|
2263
2296
|
return this.sendRequest("run_transaction" /* RUN_TRANSACTION */, payload);
|
|
2264
2297
|
}
|
|
2298
|
+
async transfer(recipient, amount, instrument, options) {
|
|
2299
|
+
const amountStr = typeof amount === "number" ? amount.toString() : amount;
|
|
2300
|
+
const resolveDate = (value, fallbackMs) => {
|
|
2301
|
+
if (value instanceof Date) {
|
|
2302
|
+
return value.toISOString();
|
|
2303
|
+
}
|
|
2304
|
+
if (typeof value === "string" && value.length > 0) {
|
|
2305
|
+
return value;
|
|
2306
|
+
}
|
|
2307
|
+
if (fallbackMs) {
|
|
2308
|
+
return new Date(Date.now() + fallbackMs).toISOString();
|
|
2309
|
+
}
|
|
2310
|
+
return new Date().toISOString();
|
|
2311
|
+
};
|
|
2312
|
+
const requestedAtIso = resolveDate(options?.requestedAt);
|
|
2313
|
+
const executeBeforeIso = resolveDate(options?.executeBefore, 24 * 60 * 60 * 1000);
|
|
2314
|
+
const transferRequest = {
|
|
2315
|
+
recipient,
|
|
2316
|
+
amount: amountStr,
|
|
2317
|
+
instrument: {
|
|
2318
|
+
instrument_admin: instrument?.instrument_admin,
|
|
2319
|
+
instrument_id: instrument?.instrument_id || "Amulet"
|
|
2320
|
+
},
|
|
2321
|
+
requested_at: requestedAtIso,
|
|
2322
|
+
execute_before: executeBeforeIso
|
|
2323
|
+
};
|
|
2324
|
+
const preparedPayload = await this.connection.prepareTransfer(this.auth_token, transferRequest);
|
|
2325
|
+
return this.submitTransaction({
|
|
2326
|
+
commands: preparedPayload.commands,
|
|
2327
|
+
disclosedContracts: preparedPayload.disclosedContracts,
|
|
2328
|
+
packageIdSelectionPreference: preparedPayload.packageIdSelectionPreference,
|
|
2329
|
+
actAs: preparedPayload.actAs,
|
|
2330
|
+
readAs: preparedPayload.readAs,
|
|
2331
|
+
synchronizerId: preparedPayload.synchronizerId
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2265
2334
|
async signMessage(message) {
|
|
2266
2335
|
return this.sendRequest("sign_raw_message" /* SIGN_RAW_MESSAGE */, message);
|
|
2267
2336
|
}
|
|
@@ -2301,6 +2370,25 @@ class Provider {
|
|
|
2301
2370
|
}
|
|
2302
2371
|
}
|
|
2303
2372
|
|
|
2373
|
+
// src/wallet.ts
|
|
2374
|
+
class LoopWallet {
|
|
2375
|
+
getProvider;
|
|
2376
|
+
constructor(getProvider) {
|
|
2377
|
+
this.getProvider = getProvider;
|
|
2378
|
+
}
|
|
2379
|
+
requireProvider() {
|
|
2380
|
+
const provider = this.getProvider();
|
|
2381
|
+
if (!provider) {
|
|
2382
|
+
throw new Error("SDK not connected. Call connect() and wait for acceptance first.");
|
|
2383
|
+
}
|
|
2384
|
+
return provider;
|
|
2385
|
+
}
|
|
2386
|
+
transfer(recipient, amount, instrument, options) {
|
|
2387
|
+
const provider = this.requireProvider();
|
|
2388
|
+
return provider.transfer(recipient, amount, instrument, options);
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2304
2392
|
// src/index.ts
|
|
2305
2393
|
class LoopSDK {
|
|
2306
2394
|
version = "0.0.1";
|
|
@@ -2314,7 +2402,10 @@ class LoopSDK {
|
|
|
2314
2402
|
onReject = null;
|
|
2315
2403
|
overlay = null;
|
|
2316
2404
|
ticketId = null;
|
|
2317
|
-
|
|
2405
|
+
wallet;
|
|
2406
|
+
constructor() {
|
|
2407
|
+
this.wallet = new LoopWallet(() => this.provider);
|
|
2408
|
+
}
|
|
2318
2409
|
init({
|
|
2319
2410
|
appName,
|
|
2320
2411
|
network,
|
|
@@ -2527,6 +2618,12 @@ class LoopSDK {
|
|
|
2527
2618
|
this.overlay = null;
|
|
2528
2619
|
}
|
|
2529
2620
|
}
|
|
2621
|
+
requireProvider() {
|
|
2622
|
+
if (!this.provider) {
|
|
2623
|
+
throw new Error("SDK not connected. Call connect() and wait for acceptance first.");
|
|
2624
|
+
}
|
|
2625
|
+
return this.provider;
|
|
2626
|
+
}
|
|
2530
2627
|
}
|
|
2531
2628
|
var loop = new LoopSDK;
|
|
2532
2629
|
export {
|