@temple-digital-group/temple-canton-js 2.0.6 → 2.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/README.md +31 -12
- package/dist/canton/deposits.js +2 -2
- package/dist/canton/wallet/adapter.d.ts +5 -5
- package/dist/canton/wallet/adapter.js +1 -1
- package/dist/canton/wallet/console.d.ts +15 -0
- package/dist/canton/wallet/console.js +232 -0
- package/dist/canton/wallet/loop.d.ts +1 -0
- package/dist/canton/wallet/loop.js +16 -0
- package/dist/canton/wallet/registry.d.ts +2 -0
- package/dist/canton/wallet/registry.js +16 -0
- package/dist/canton/wallet/service.d.ts +1 -1
- package/dist/canton/walletAdapter.d.ts +5 -3
- package/dist/canton/walletAdapter.js +6 -7
- package/dist/canton/withdrawals.js +3 -3
- package/package.json +1 -1
- package/src/api/config.d.ts +7 -0
- package/src/canton/deposits.ts +2 -2
- package/src/canton/index.js +8 -8
- package/src/canton/wallet/adapter.ts +5 -5
- package/src/canton/wallet/console.ts +281 -0
- package/src/canton/wallet/loop.ts +19 -0
- package/src/canton/wallet/registry.ts +26 -0
- package/src/canton/wallet/service.ts +1 -1
- package/src/canton/walletAdapter.ts +7 -7
- package/src/canton/withdrawals.ts +3 -3
- package/src/config/index.d.ts +7 -0
- package/src/config/index.js +1 -0
package/README.md
CHANGED
|
@@ -14,18 +14,19 @@ Call `initialize()` before using any SDK functions. It sets up the config and op
|
|
|
14
14
|
|
|
15
15
|
### Wallet Adapter
|
|
16
16
|
|
|
17
|
-
For apps using
|
|
17
|
+
For apps using a supported wallet, just pass the wallet instance as `WALLET_ADAPTER` (or to `setWalletAdapter`). The SDK recognizes supported wallets and wraps them automatically with default settings — you don't need to call an adapter factory yourself.
|
|
18
18
|
|
|
19
|
-
- **
|
|
20
|
-
- **
|
|
19
|
+
- **Loop:** pass the Loop SDK instance directly. Works both in the browser and server-side (Node) — Loop signs locally on the server or delegates to the Loop Wallet UI in the browser.
|
|
20
|
+
- **Console:** **browser only** — pass the Console wallet instance directly. Reads use `getPrimaryAccount()` and `getContracts()`, and commands are submitted through Console's `prepareExecuteAndWait()` (or `prepareExecute()`) — the same Temple Daml command object Loop receives. It can't be used in a server/headless (Node) environment.
|
|
21
21
|
|
|
22
22
|
```javascript
|
|
23
23
|
import { initialize } from "@temple-digital-group/temple-canton-js";
|
|
24
24
|
|
|
25
|
+
// `wallet` is a supported wallet instance (e.g. a Loop SDK or Console wallet instance).
|
|
25
26
|
initialize({
|
|
26
27
|
API_KEY: "your-api-key",
|
|
27
28
|
NETWORK: "mainnet",
|
|
28
|
-
WALLET_ADAPTER:
|
|
29
|
+
WALLET_ADAPTER: wallet,
|
|
29
30
|
});
|
|
30
31
|
```
|
|
31
32
|
|
|
@@ -34,14 +35,32 @@ You can also set or change the wallet adapter after init:
|
|
|
34
35
|
```javascript
|
|
35
36
|
import { setWalletAdapter } from "@temple-digital-group/temple-canton-js";
|
|
36
37
|
|
|
37
|
-
setWalletAdapter(
|
|
38
|
+
setWalletAdapter(wallet);
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
#### Adapter Factories (advanced)
|
|
42
|
+
|
|
43
|
+
You only need the `create*WalletAdapter()` factories when you want to customize how a wallet is wrapped — passing a raw instance (above) already calls them for you with defaults. When you do need custom settings, build the adapter and hand the result to `WALLET_ADAPTER` / `setWalletAdapter`:
|
|
44
|
+
|
|
45
|
+
- `createLoopWalletAdapter(loop)` — normalize a Loop instance (no extra options).
|
|
46
|
+
- `createConsoleWalletAdapter(consoleWallet, options?)` — normalize a Console instance (browser only) with optional overrides:
|
|
47
|
+
- `network` — Console network variant (`CANTON_NETWORK`, `CANTON_NETWORK_TEST`, `CANTON_NETWORK_DEV`); defaults from `NETWORK`.
|
|
48
|
+
- `partyId` — seed a synchronous party id instead of resolving it from `getPrimaryAccount()`.
|
|
49
|
+
- `parties` — explicit read parties (defaults to the active account party).
|
|
50
|
+
- `waitForExecution` — `true` (default) submits via `prepareExecuteAndWait()`; `false` uses `prepareExecute()`.
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
import { setWalletAdapter, createConsoleWalletAdapter } from "@temple-digital-group/temple-canton-js";
|
|
54
|
+
|
|
55
|
+
// Only needed for custom options — otherwise just pass the raw instance.
|
|
56
|
+
setWalletAdapter(createConsoleWalletAdapter(consoleWallet, { network: "mainnet" }));
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| Key | Required | Description |
|
|
60
|
+
| ---------------- | -------- | ------------------------------------------------- |
|
|
61
|
+
| `API_KEY` | Yes | Temple REST API key |
|
|
62
|
+
| `NETWORK` | Yes | `mainnet` or `testnet` |
|
|
63
|
+
| `WALLET_ADAPTER` | Yes | Supported wallet instance or normalized adapter |
|
|
45
64
|
|
|
46
65
|
## Supported Instruments
|
|
47
66
|
|
|
@@ -344,14 +363,14 @@ const unsubOrder = ws.onUserEvent("user_order", (data) => { ... });
|
|
|
344
363
|
|
|
345
364
|
## API Reference
|
|
346
365
|
|
|
347
|
-
> Functions marked with **W** support
|
|
366
|
+
> Functions marked with **W** support configured wallets via the wallet adapter.
|
|
348
367
|
|
|
349
368
|
### Configuration
|
|
350
369
|
|
|
351
370
|
| Function | Description |
|
|
352
371
|
| --------------------------- | ----------------------------------------------------------------------------- |
|
|
353
372
|
| `initialize(config)` | Initialize the SDK, set config, and optionally authenticate with the REST API |
|
|
354
|
-
| `setWalletAdapter(adapter)` | Set or update the
|
|
373
|
+
| `setWalletAdapter(adapter)` | Set or update the wallet adapter for all wallet-aware functions |
|
|
355
374
|
|
|
356
375
|
### Instrument Catalog
|
|
357
376
|
|
package/dist/canton/deposits.js
CHANGED
|
@@ -120,7 +120,7 @@ export async function prepareDepositHoldings(amount, symbol) {
|
|
|
120
120
|
if (!provider && !config.VALIDATOR_SCAN_API_URL) {
|
|
121
121
|
return { error: "prepareDepositHoldings: wallet provider is required to prepare holdings. Connect a wallet adapter." };
|
|
122
122
|
}
|
|
123
|
-
const party = getAdapterPartyId() ?? config.VALIDATOR_USER_PARTY_ID;
|
|
123
|
+
const party = (await getAdapterPartyId()) ?? config.VALIDATOR_USER_PARTY_ID;
|
|
124
124
|
if (!party) {
|
|
125
125
|
return { error: "prepareDepositHoldings: party ID is required. Connect a wallet adapter or configure VALIDATOR_USER_PARTY_ID." };
|
|
126
126
|
}
|
|
@@ -212,7 +212,7 @@ export async function deposit(amount, symbol) {
|
|
|
212
212
|
if (!getWalletAdapter()) {
|
|
213
213
|
return { error: "deposit: wallet adapter is required. Call setWalletAdapter() first." };
|
|
214
214
|
}
|
|
215
|
-
const party = getAdapterPartyId();
|
|
215
|
+
const party = await getAdapterPartyId();
|
|
216
216
|
if (!party) {
|
|
217
217
|
return { error: "deposit: could not resolve party ID from wallet adapter." };
|
|
218
218
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Universal Wallet Adapter contract.
|
|
3
3
|
*
|
|
4
|
-
* Every wallet
|
|
4
|
+
* Every wallet provider is
|
|
5
5
|
* represented as a *normalized adapter* implementing the capability interface
|
|
6
6
|
* defined here. The rest of the SDK never talks to a wallet/provider SDK
|
|
7
7
|
* directly — it goes through the wallet service (./service.js), which dispatches
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
*/
|
|
26
26
|
/** A normalized wallet adapter produced by {@link defineWalletAdapter}. */
|
|
27
27
|
export interface WalletAdapter {
|
|
28
|
-
/** Provider id, e.g. "loop". */
|
|
28
|
+
/** Provider id, e.g. "loop" or "console". */
|
|
29
29
|
readonly id: string;
|
|
30
30
|
/** True for server-side adapters that sign/submit locally. */
|
|
31
31
|
readonly isServer: boolean;
|
|
32
|
-
/** Resolve the wallet's primary party id. */
|
|
33
|
-
getPartyId(): string | null
|
|
32
|
+
/** Resolve the wallet's primary party id. May resolve asynchronously. */
|
|
33
|
+
getPartyId(): Promise<string | null>;
|
|
34
34
|
/** Read active contracts matching `args` via the wallet. */
|
|
35
35
|
getActiveContracts(args: unknown): Promise<unknown>;
|
|
36
36
|
/** Sign and submit a ledger command via the wallet. */
|
|
@@ -52,7 +52,7 @@ export interface WalletAdapter {
|
|
|
52
52
|
export interface WalletAdapterDefinition {
|
|
53
53
|
id?: string;
|
|
54
54
|
isServer?: boolean;
|
|
55
|
-
getPartyId(): string | null
|
|
55
|
+
getPartyId(): string | null | Promise<string | null>;
|
|
56
56
|
getActiveContracts(args: unknown): Promise<unknown> | unknown;
|
|
57
57
|
submitCommand(command: unknown): Promise<unknown> | unknown;
|
|
58
58
|
payDueGasIfAny?(): Promise<void> | void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Universal Wallet Adapter contract.
|
|
3
3
|
*
|
|
4
|
-
* Every wallet
|
|
4
|
+
* Every wallet provider is
|
|
5
5
|
* represented as a *normalized adapter* implementing the capability interface
|
|
6
6
|
* defined here. The rest of the SDK never talks to a wallet/provider SDK
|
|
7
7
|
* directly — it goes through the wallet service (./service.js), which dispatches
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type WalletAdapter } from "./adapter.js";
|
|
2
|
+
type ConsoleNetworkVariant = "CANTON_NETWORK_DEV" | "CANTON_NETWORK_TEST" | "CANTON_NETWORK";
|
|
3
|
+
export interface ConsoleWalletAdapterOptions {
|
|
4
|
+
/** Console network id. Defaults from config.NETWORK when omitted. */
|
|
5
|
+
network?: ConsoleNetworkVariant | "localhost" | "testnet" | "mainnet" | string;
|
|
6
|
+
/** Optional party id seed for SDK call sites that need a synchronous party. */
|
|
7
|
+
partyId?: string;
|
|
8
|
+
/** Optional explicit read parties. Defaults to the active Console account party. */
|
|
9
|
+
parties?: string[];
|
|
10
|
+
/** Use prepareExecuteAndWait when available. Defaults to true. */
|
|
11
|
+
waitForExecution?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function isConsoleWalletLike(value: unknown): boolean;
|
|
14
|
+
export declare function createConsoleWalletAdapter(consoleWallet: unknown, options?: ConsoleWalletAdapterOptions): WalletAdapter;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import config from "../../../src/config/index.js";
|
|
2
|
+
import { defineWalletAdapter } from "./adapter.js";
|
|
3
|
+
function hasConsoleSubmitCapability(value) {
|
|
4
|
+
return typeof value.prepareExecute === "function" || typeof value.prepareExecuteAndWait === "function";
|
|
5
|
+
}
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
8
|
+
}
|
|
9
|
+
function isPromiseLike(value) {
|
|
10
|
+
return isRecord(value) && typeof value.then === "function";
|
|
11
|
+
}
|
|
12
|
+
function asStringArray(value) {
|
|
13
|
+
if (Array.isArray(value))
|
|
14
|
+
return value.filter((entry) => typeof entry === "string" && entry.length > 0);
|
|
15
|
+
if (typeof value === "string" && value.length > 0)
|
|
16
|
+
return [value];
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
function firstString(...values) {
|
|
20
|
+
for (const value of values) {
|
|
21
|
+
if (typeof value === "string" && value.length > 0)
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
function firstRecord(...values) {
|
|
27
|
+
for (const value of values) {
|
|
28
|
+
if (isRecord(value))
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
function resolveConsoleWallet(input) {
|
|
34
|
+
const candidate = isRecord(input) && isRecord(input.consoleWallet) ? input.consoleWallet : input;
|
|
35
|
+
if (!isRecord(candidate)) {
|
|
36
|
+
throw new Error("[Temple SDK] createConsoleWalletAdapter requires a Console wallet SDK instance.");
|
|
37
|
+
}
|
|
38
|
+
if (typeof candidate.getPrimaryAccount !== "function" || typeof candidate.getContracts !== "function") {
|
|
39
|
+
throw new Error("[Temple SDK] Console wallet SDK must expose getPrimaryAccount() and getContracts().");
|
|
40
|
+
}
|
|
41
|
+
if (!hasConsoleSubmitCapability(candidate)) {
|
|
42
|
+
throw new Error("[Temple SDK] Console wallet SDK must expose prepareExecute() or prepareExecuteAndWait().");
|
|
43
|
+
}
|
|
44
|
+
return candidate;
|
|
45
|
+
}
|
|
46
|
+
export function isConsoleWalletLike(value) {
|
|
47
|
+
const candidate = isRecord(value) && isRecord(value.consoleWallet) ? value.consoleWallet : value;
|
|
48
|
+
return isRecord(candidate) && typeof candidate.getPrimaryAccount === "function" && typeof candidate.getContracts === "function" && hasConsoleSubmitCapability(candidate);
|
|
49
|
+
}
|
|
50
|
+
function resolveNetwork(network) {
|
|
51
|
+
const configured = String(network || config.NETWORK || "").toLowerCase();
|
|
52
|
+
switch (configured) {
|
|
53
|
+
case "localhost":
|
|
54
|
+
case "local":
|
|
55
|
+
case "dev":
|
|
56
|
+
case "devnet":
|
|
57
|
+
return "CANTON_NETWORK_DEV";
|
|
58
|
+
case "testnet":
|
|
59
|
+
case "test":
|
|
60
|
+
return "CANTON_NETWORK_TEST";
|
|
61
|
+
case "mainnet":
|
|
62
|
+
case "main":
|
|
63
|
+
return "CANTON_NETWORK";
|
|
64
|
+
default:
|
|
65
|
+
return network || "CANTON_NETWORK";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function extractPartyId(account) {
|
|
69
|
+
return typeof account?.partyId === "string" && account.partyId ? account.partyId : null;
|
|
70
|
+
}
|
|
71
|
+
function extractTemplateIds(args) {
|
|
72
|
+
if (!isRecord(args))
|
|
73
|
+
return [];
|
|
74
|
+
const direct = [...asStringArray(args.templateIds), ...asStringArray(args.templateId)];
|
|
75
|
+
if (direct.length > 0)
|
|
76
|
+
return direct;
|
|
77
|
+
const filter = firstRecord(args.filter);
|
|
78
|
+
const filtersByParty = firstRecord(filter?.filtersByParty);
|
|
79
|
+
const templateIds = [];
|
|
80
|
+
for (const partyFilter of Object.values(filtersByParty || {})) {
|
|
81
|
+
const cumulative = firstRecord(partyFilter)?.cumulative;
|
|
82
|
+
if (!Array.isArray(cumulative))
|
|
83
|
+
continue;
|
|
84
|
+
for (const entry of cumulative) {
|
|
85
|
+
const identifierFilter = firstRecord(entry)?.identifierFilter;
|
|
86
|
+
const templateFilter = firstRecord(firstRecord(identifierFilter)?.["TemplateFilter"])?.value;
|
|
87
|
+
templateIds.push(...asStringArray(firstRecord(templateFilter)?.templateId));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return templateIds;
|
|
91
|
+
}
|
|
92
|
+
function extractParties(args, fallbackParty, optionParties) {
|
|
93
|
+
if (optionParties?.length)
|
|
94
|
+
return optionParties;
|
|
95
|
+
if (isRecord(args)) {
|
|
96
|
+
const direct = [...asStringArray(args.parties), ...asStringArray(args.party)];
|
|
97
|
+
if (direct.length > 0)
|
|
98
|
+
return direct;
|
|
99
|
+
const filtersByParty = firstRecord(firstRecord(args.filter)?.filtersByParty);
|
|
100
|
+
const filteredParties = Object.keys(filtersByParty || {});
|
|
101
|
+
if (filteredParties.length > 0)
|
|
102
|
+
return filteredParties;
|
|
103
|
+
}
|
|
104
|
+
return fallbackParty ? [fallbackParty] : [];
|
|
105
|
+
}
|
|
106
|
+
function unwrapContractItems(response) {
|
|
107
|
+
if (Array.isArray(response))
|
|
108
|
+
return response;
|
|
109
|
+
if (!isRecord(response))
|
|
110
|
+
return [];
|
|
111
|
+
for (const key of ["items", "activeContracts", "contracts", "result"]) {
|
|
112
|
+
const value = response[key];
|
|
113
|
+
if (Array.isArray(value))
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
function normalizeContractItem(item) {
|
|
119
|
+
if (!isRecord(item))
|
|
120
|
+
return null;
|
|
121
|
+
const contractEntry = firstRecord(item.contractEntry) || item;
|
|
122
|
+
const jsActive = firstRecord(contractEntry.JsActiveContract, contractEntry.jsActiveContract, contractEntry.activeContract) || contractEntry;
|
|
123
|
+
const createdEvent = firstRecord(jsActive.createdEvent, item.createdEvent, item.contract, jsActive) || {};
|
|
124
|
+
const createArgument = firstRecord(createdEvent.createArgument, createdEvent.create_argument, createdEvent.payload, item.payload) || {};
|
|
125
|
+
const contractId = firstString(createdEvent.contractId, createdEvent.contract_id, item.contractId, item.contract_id);
|
|
126
|
+
const templateId = firstString(createdEvent.templateId, createdEvent.template_id, jsActive.templateId, item.templateId, item.template_id);
|
|
127
|
+
const createdEventBlob = firstString(createdEvent.createdEventBlob, createdEvent.created_event_blob, createdEvent.eventBlob, item.createdEventBlob, item.created_event_blob, item.eventBlob);
|
|
128
|
+
const synchronizerId = firstString(jsActive.synchronizerId, jsActive.synchronizer_id, item.synchronizerId, item.synchronizer_id, item.domainId, item.domain_id);
|
|
129
|
+
if (!contractId && !templateId && !createdEventBlob)
|
|
130
|
+
return null;
|
|
131
|
+
return {
|
|
132
|
+
contractEntry: {
|
|
133
|
+
JsActiveContract: {
|
|
134
|
+
...jsActive,
|
|
135
|
+
createdEvent: {
|
|
136
|
+
...createdEvent,
|
|
137
|
+
contractId,
|
|
138
|
+
templateId,
|
|
139
|
+
createArgument,
|
|
140
|
+
createdEventBlob,
|
|
141
|
+
},
|
|
142
|
+
synchronizerId,
|
|
143
|
+
templateId,
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function normalizeContractsResponse(response) {
|
|
149
|
+
return unwrapContractItems(response)
|
|
150
|
+
.map(normalizeContractItem)
|
|
151
|
+
.filter((entry) => entry !== null);
|
|
152
|
+
}
|
|
153
|
+
function extractErrorDetail(error) {
|
|
154
|
+
if (!isRecord(error))
|
|
155
|
+
return String(error);
|
|
156
|
+
const response = isRecord(error.response) ? error.response : undefined;
|
|
157
|
+
const data = response && response.data !== undefined ? response.data : undefined;
|
|
158
|
+
if (typeof data === "string")
|
|
159
|
+
return data;
|
|
160
|
+
if (isRecord(data))
|
|
161
|
+
return JSON.stringify(data);
|
|
162
|
+
if (typeof error.message === "string")
|
|
163
|
+
return error.message;
|
|
164
|
+
return String(error);
|
|
165
|
+
}
|
|
166
|
+
function wrapConsoleSubmitError(error) {
|
|
167
|
+
const detail = extractErrorDetail(error);
|
|
168
|
+
return new Error(`[Temple SDK] Console wallet submit failed: ${detail}.`);
|
|
169
|
+
}
|
|
170
|
+
function normalizeLedgerCommand(command) {
|
|
171
|
+
if (!isRecord(command) || !Array.isArray(command.commands)) {
|
|
172
|
+
throw new Error("[Temple SDK] Console wallet submitCommand() expects a ledger command with a commands array.");
|
|
173
|
+
}
|
|
174
|
+
return command;
|
|
175
|
+
}
|
|
176
|
+
export function createConsoleWalletAdapter(consoleWallet, options = {}) {
|
|
177
|
+
const wallet = resolveConsoleWallet(consoleWallet);
|
|
178
|
+
let cachedPartyId = options.partyId || null;
|
|
179
|
+
let pendingPartyId = null;
|
|
180
|
+
const loadPartyId = async () => {
|
|
181
|
+
const account = await wallet.getPrimaryAccount();
|
|
182
|
+
cachedPartyId = extractPartyId(account);
|
|
183
|
+
pendingPartyId = null;
|
|
184
|
+
return cachedPartyId;
|
|
185
|
+
};
|
|
186
|
+
const ensurePartyId = async () => {
|
|
187
|
+
if (cachedPartyId)
|
|
188
|
+
return cachedPartyId;
|
|
189
|
+
if (!pendingPartyId)
|
|
190
|
+
pendingPartyId = loadPartyId();
|
|
191
|
+
return pendingPartyId;
|
|
192
|
+
};
|
|
193
|
+
return defineWalletAdapter({
|
|
194
|
+
id: "console",
|
|
195
|
+
isServer: false,
|
|
196
|
+
getRawProvider: () => wallet,
|
|
197
|
+
getPartyId: ensurePartyId,
|
|
198
|
+
getActiveContracts: async (args) => {
|
|
199
|
+
const partyId = await ensurePartyId();
|
|
200
|
+
const templateIds = extractTemplateIds(args);
|
|
201
|
+
const parties = extractParties(args, partyId, options.parties);
|
|
202
|
+
if (templateIds.length === 0) {
|
|
203
|
+
throw new Error("[Temple SDK] Console wallet getActiveContracts() requires at least one templateId.");
|
|
204
|
+
}
|
|
205
|
+
if (parties.length === 0) {
|
|
206
|
+
throw new Error("[Temple SDK] Console wallet getActiveContracts() requires a party id from getPrimaryAccount() or adapter options.");
|
|
207
|
+
}
|
|
208
|
+
const response = await wallet.getContracts({
|
|
209
|
+
network: resolveNetwork(options.network),
|
|
210
|
+
parties,
|
|
211
|
+
templateIds,
|
|
212
|
+
});
|
|
213
|
+
return normalizeContractsResponse(response);
|
|
214
|
+
},
|
|
215
|
+
submitCommand: async (command) => {
|
|
216
|
+
// resolveConsoleWallet() guarantees at least one prepare method exists.
|
|
217
|
+
const prepareRequest = normalizeLedgerCommand(command);
|
|
218
|
+
const useWait = typeof wallet.prepareExecuteAndWait === "function" &&
|
|
219
|
+
(options.waitForExecution !== false || typeof wallet.prepareExecute !== "function");
|
|
220
|
+
try {
|
|
221
|
+
return await (useWait ? wallet.prepareExecuteAndWait(prepareRequest) : wallet.prepareExecute(prepareRequest));
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
throw wrapConsoleSubmitError(error);
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
disconnect: async () => {
|
|
228
|
+
if (typeof wallet.disconnect === "function")
|
|
229
|
+
await wallet.disconnect();
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* has a null connection.ticketId and connection.ws.
|
|
16
16
|
*/
|
|
17
17
|
import { type WalletAdapter } from "./adapter.js";
|
|
18
|
+
export declare function isLoopWalletLike(value: unknown): boolean;
|
|
18
19
|
/**
|
|
19
20
|
* Create a universal wallet adapter backed by a Loop SDK instance.
|
|
20
21
|
*/
|
|
@@ -15,6 +15,19 @@
|
|
|
15
15
|
* has a null connection.ticketId and connection.ws.
|
|
16
16
|
*/
|
|
17
17
|
import { defineWalletAdapter } from "./adapter.js";
|
|
18
|
+
function isRecord(value) {
|
|
19
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
20
|
+
}
|
|
21
|
+
export function isLoopWalletLike(value) {
|
|
22
|
+
if (!isRecord(value))
|
|
23
|
+
return false;
|
|
24
|
+
const provider = isRecord(value.provider) ? value.provider : value;
|
|
25
|
+
return (typeof provider.getActiveContracts === "function" &&
|
|
26
|
+
(typeof value.executeTransaction === "function" ||
|
|
27
|
+
typeof provider.submitTransaction === "function" ||
|
|
28
|
+
isRecord(value.session) ||
|
|
29
|
+
typeof provider.party_id === "string"));
|
|
30
|
+
}
|
|
18
31
|
/**
|
|
19
32
|
* Detect whether a Loop instance is server-side.
|
|
20
33
|
* Loop-specific: server-side has null connection.ticketId and connection.ws.
|
|
@@ -33,6 +46,9 @@ export function createLoopWalletAdapter(loop) {
|
|
|
33
46
|
if (!loop || typeof loop !== "object") {
|
|
34
47
|
throw new Error("[Temple SDK] createLoopWalletAdapter requires a Loop wallet instance.");
|
|
35
48
|
}
|
|
49
|
+
if (!isLoopWalletLike(loop)) {
|
|
50
|
+
throw new Error("[Temple SDK] createLoopWalletAdapter received an unsupported Loop wallet instance.");
|
|
51
|
+
}
|
|
36
52
|
const sdk = loop;
|
|
37
53
|
const isServer = detectServerSide(sdk);
|
|
38
54
|
// The provider sub-object handles reads (getActiveContracts) and client-side
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { isWalletAdapter } from "./adapter.js";
|
|
2
|
+
import { createConsoleWalletAdapter, isConsoleWalletLike } from "./console.js";
|
|
3
|
+
import { createLoopWalletAdapter, isLoopWalletLike } from "./loop.js";
|
|
4
|
+
const BUILT_IN_FACTORIES = [
|
|
5
|
+
{ id: "console", canWrap: isConsoleWalletLike, wrap: (value) => createConsoleWalletAdapter(value) },
|
|
6
|
+
{ id: "loop", canWrap: isLoopWalletLike, wrap: createLoopWalletAdapter },
|
|
7
|
+
];
|
|
8
|
+
export function normalizeWalletAdapter(adapter) {
|
|
9
|
+
if (isWalletAdapter(adapter))
|
|
10
|
+
return adapter;
|
|
11
|
+
for (const factory of BUILT_IN_FACTORIES) {
|
|
12
|
+
if (factory.canWrap(adapter))
|
|
13
|
+
return factory.wrap(adapter);
|
|
14
|
+
}
|
|
15
|
+
throw new Error("[Temple SDK] Unsupported wallet adapter. Pass a normalized adapter from createLoopWalletAdapter(), createConsoleWalletAdapter(), or defineWalletAdapter().");
|
|
16
|
+
}
|
|
@@ -21,7 +21,7 @@ export declare function getActiveAdapter(): WalletAdapter | null;
|
|
|
21
21
|
/** True when a wallet adapter is configured. */
|
|
22
22
|
export declare function hasActiveAdapter(): boolean;
|
|
23
23
|
/** Resolve the active wallet's party id. Throws when no adapter is configured. */
|
|
24
|
-
export declare function getPartyId(): string | null
|
|
24
|
+
export declare function getPartyId(): Promise<string | null>;
|
|
25
25
|
/** Sign and submit a ledger command. Throws when no adapter is configured. */
|
|
26
26
|
export declare function submitCommand(command: unknown): Promise<unknown>;
|
|
27
27
|
/**
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Backward-compatible public surface for wallet interactions. The real wallet
|
|
5
5
|
* architecture lives in ./wallet/ — a universal adapter contract (adapter.ts),
|
|
6
6
|
* a service registry that dispatches capability calls (service.ts), and one
|
|
7
|
-
* factory per wallet
|
|
7
|
+
* factory per wallet provider. This module is a thin
|
|
8
8
|
* facade over that service so existing imports keep working unchanged.
|
|
9
9
|
*
|
|
10
10
|
* Adding a new wallet does not touch this file: write a create<Name>WalletAdapter()
|
|
@@ -12,13 +12,15 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import type { WalletAdapter } from "./wallet/adapter.js";
|
|
14
14
|
export { createLoopWalletAdapter } from "./wallet/loop.js";
|
|
15
|
+
export { createConsoleWalletAdapter } from "./wallet/console.js";
|
|
15
16
|
export { defineWalletAdapter, isWalletAdapter } from "./wallet/adapter.js";
|
|
16
17
|
export type { WalletAdapter, WalletAdapterDefinition } from "./wallet/adapter.js";
|
|
18
|
+
export type { ConsoleWalletAdapterOptions } from "./wallet/console.js";
|
|
17
19
|
/**
|
|
18
20
|
* Set the active wallet adapter.
|
|
19
21
|
*
|
|
20
22
|
* Accepts either a normalized adapter (from a create*WalletAdapter() factory) or
|
|
21
|
-
* a raw
|
|
23
|
+
* a raw wallet instance recognized by a built-in wallet factory.
|
|
22
24
|
* Pass a falsy value to clear the adapter.
|
|
23
25
|
*/
|
|
24
26
|
export declare function setWalletAdapter(adapter: unknown): void;
|
|
@@ -38,7 +40,7 @@ export declare function isServerMode(): boolean;
|
|
|
38
40
|
/**
|
|
39
41
|
* Get the party ID from the active wallet adapter, or null when none is set.
|
|
40
42
|
*/
|
|
41
|
-
export declare function getAdapterPartyId(): string | null
|
|
43
|
+
export declare function getAdapterPartyId(): Promise<string | null>;
|
|
42
44
|
/**
|
|
43
45
|
* Pay any outstanding network gas before submitting a transaction or reading
|
|
44
46
|
* balances. Safe no-op when no adapter is configured or the wallet handles gas
|
|
@@ -4,23 +4,23 @@
|
|
|
4
4
|
* Backward-compatible public surface for wallet interactions. The real wallet
|
|
5
5
|
* architecture lives in ./wallet/ — a universal adapter contract (adapter.ts),
|
|
6
6
|
* a service registry that dispatches capability calls (service.ts), and one
|
|
7
|
-
* factory per wallet
|
|
7
|
+
* factory per wallet provider. This module is a thin
|
|
8
8
|
* facade over that service so existing imports keep working unchanged.
|
|
9
9
|
*
|
|
10
10
|
* Adding a new wallet does not touch this file: write a create<Name>WalletAdapter()
|
|
11
11
|
* factory and pass its result to setWalletAdapter().
|
|
12
12
|
*/
|
|
13
13
|
import { setActiveAdapter, getActiveAdapter, submitCommand as serviceSubmitCommand, payDueGasIfAny as servicePayDueGasIfAny, } from "./wallet/service.js";
|
|
14
|
-
import {
|
|
15
|
-
import { createLoopWalletAdapter } from "./wallet/loop.js";
|
|
14
|
+
import { normalizeWalletAdapter } from "./wallet/registry.js";
|
|
16
15
|
// Re-export the adapter toolkit so consumers can build/register custom wallets.
|
|
17
16
|
export { createLoopWalletAdapter } from "./wallet/loop.js";
|
|
17
|
+
export { createConsoleWalletAdapter } from "./wallet/console.js";
|
|
18
18
|
export { defineWalletAdapter, isWalletAdapter } from "./wallet/adapter.js";
|
|
19
19
|
/**
|
|
20
20
|
* Set the active wallet adapter.
|
|
21
21
|
*
|
|
22
22
|
* Accepts either a normalized adapter (from a create*WalletAdapter() factory) or
|
|
23
|
-
* a raw
|
|
23
|
+
* a raw wallet instance recognized by a built-in wallet factory.
|
|
24
24
|
* Pass a falsy value to clear the adapter.
|
|
25
25
|
*/
|
|
26
26
|
export function setWalletAdapter(adapter) {
|
|
@@ -28,8 +28,7 @@ export function setWalletAdapter(adapter) {
|
|
|
28
28
|
setActiveAdapter(null);
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
setActiveAdapter(normalized);
|
|
31
|
+
setActiveAdapter(normalizeWalletAdapter(adapter));
|
|
33
32
|
}
|
|
34
33
|
/**
|
|
35
34
|
* Get the active (normalized) wallet adapter, or null when none is set.
|
|
@@ -57,7 +56,7 @@ export function isServerMode() {
|
|
|
57
56
|
/**
|
|
58
57
|
* Get the party ID from the active wallet adapter, or null when none is set.
|
|
59
58
|
*/
|
|
60
|
-
export function getAdapterPartyId() {
|
|
59
|
+
export async function getAdapterPartyId() {
|
|
61
60
|
const adapter = getActiveAdapter();
|
|
62
61
|
return adapter ? adapter.getPartyId() : null;
|
|
63
62
|
}
|
|
@@ -20,7 +20,7 @@ const CC_FEE_RESERVE = 10;
|
|
|
20
20
|
export async function finalizeWithdrawFunds(opts, returnCommand = false) {
|
|
21
21
|
const { allocationId, sender: senderOpt, assetId: rawAssetId, disclosures, userId } = opts;
|
|
22
22
|
const assetId = normalizeAssetId(rawAssetId);
|
|
23
|
-
const sender = getAdapterPartyId() ?? senderOpt ?? config.VALIDATOR_USER_PARTY_ID;
|
|
23
|
+
const sender = (await getAdapterPartyId()) ?? senderOpt ?? config.VALIDATOR_USER_PARTY_ID;
|
|
24
24
|
if (!allocationId || !sender || !assetId) {
|
|
25
25
|
const msg = "finalizeWithdrawFunds: allocationId, sender, and assetId are required";
|
|
26
26
|
console.error(msg);
|
|
@@ -267,7 +267,7 @@ export async function finalizeWithdrawFunds(opts, returnCommand = false) {
|
|
|
267
267
|
export async function withdrawFunds(opts, returnCommand = false) {
|
|
268
268
|
const { amount, pollIntervalMs = 2000, maxPollAttempts = 30 } = opts || {};
|
|
269
269
|
const asset_id = normalizeAssetId(opts?.asset_id);
|
|
270
|
-
const sender = getAdapterPartyId() ?? config.VALIDATOR_USER_PARTY_ID;
|
|
270
|
+
const sender = (await getAdapterPartyId()) ?? config.VALIDATOR_USER_PARTY_ID;
|
|
271
271
|
if (!sender) {
|
|
272
272
|
const msg = "withdrawFunds: sender party is required. Connect a wallet adapter or configure VALIDATOR_USER_PARTY_ID.";
|
|
273
273
|
console.error(msg);
|
|
@@ -343,7 +343,7 @@ export async function withdrawFunds(opts, returnCommand = false) {
|
|
|
343
343
|
* which archives the delegation and revokes the operator's authority.
|
|
344
344
|
*/
|
|
345
345
|
export async function withdrawDelegation(delegationId = null, user = null, returnCommand = false) {
|
|
346
|
-
let resolvedUser = user ?? getAdapterPartyId() ?? config.VALIDATOR_USER_PARTY_ID;
|
|
346
|
+
let resolvedUser = user ?? (await getAdapterPartyId()) ?? config.VALIDATOR_USER_PARTY_ID;
|
|
347
347
|
let resolvedDelegationId = delegationId;
|
|
348
348
|
// If no delegationId passed, fetch it from the API
|
|
349
349
|
if (!resolvedDelegationId) {
|
package/package.json
CHANGED
package/src/api/config.d.ts
CHANGED
|
@@ -17,4 +17,11 @@ declare module "../../src/config/index.js" {
|
|
|
17
17
|
export function setWalletAdapter(adapter: unknown): void;
|
|
18
18
|
export function getWalletAdapter(): unknown;
|
|
19
19
|
export function getAdapterProvider(): unknown;
|
|
20
|
+
export interface ConsoleWalletAdapterOptions {
|
|
21
|
+
network?: string;
|
|
22
|
+
partyId?: string;
|
|
23
|
+
parties?: string[];
|
|
24
|
+
waitForExecution?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export function createConsoleWalletAdapter(consoleWallet: unknown, options?: ConsoleWalletAdapterOptions): unknown;
|
|
20
27
|
}
|
package/src/canton/deposits.ts
CHANGED
|
@@ -198,7 +198,7 @@ export async function prepareDepositHoldings(
|
|
|
198
198
|
return { error: "prepareDepositHoldings: wallet provider is required to prepare holdings. Connect a wallet adapter." };
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
const party = getAdapterPartyId() ?? config.VALIDATOR_USER_PARTY_ID;
|
|
201
|
+
const party = (await getAdapterPartyId()) ?? config.VALIDATOR_USER_PARTY_ID;
|
|
202
202
|
if (!party) {
|
|
203
203
|
return { error: "prepareDepositHoldings: party ID is required. Connect a wallet adapter or configure VALIDATOR_USER_PARTY_ID." };
|
|
204
204
|
}
|
|
@@ -306,7 +306,7 @@ export async function deposit(
|
|
|
306
306
|
return { error: "deposit: wallet adapter is required. Call setWalletAdapter() first." };
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
-
const party = getAdapterPartyId();
|
|
309
|
+
const party = await getAdapterPartyId();
|
|
310
310
|
if (!party) {
|
|
311
311
|
return { error: "deposit: could not resolve party ID from wallet adapter." };
|
|
312
312
|
}
|
package/src/canton/index.js
CHANGED
|
@@ -1438,7 +1438,7 @@ export async function getCandidateMiningRoundContract(dso, returnCommand = false
|
|
|
1438
1438
|
* Get Amulet holdings for a party from the ledger or a provider.
|
|
1439
1439
|
* @param {string} party - The party ID
|
|
1440
1440
|
* @param {boolean} [returnCommand=false] - If true, returns the raw command/endpoint instead of executing
|
|
1441
|
-
* @param {Object|null} [provider=null] - Optional
|
|
1441
|
+
* @param {Object|null} [provider=null] - Optional wallet provider to use instead of ledger API
|
|
1442
1442
|
* @returns {Promise<Object|null>} Holdings data, or null on failure
|
|
1443
1443
|
*/
|
|
1444
1444
|
export async function getAmuletHoldingsForParty(party, returnCommand = false, provider = null) {
|
|
@@ -1948,7 +1948,7 @@ export async function getCandidateHoldingForOrderCreation(party, isAmulet, requi
|
|
|
1948
1948
|
* returns the command for the wallet to sign instead of submitting directly.
|
|
1949
1949
|
* @param {string} party - The party ID
|
|
1950
1950
|
* @param {boolean} [returnCommand=false] - If true, returns the raw command/endpoint instead of executing
|
|
1951
|
-
* @param {Object|null} [provider=null] - Optional
|
|
1951
|
+
* @param {Object|null} [provider=null] - Optional wallet provider to use instead of ledger API
|
|
1952
1952
|
* @param {number|null} [maxUtxos=null] - Maximum number of UTXOs to merge (picks smallest first). Null = merge all.
|
|
1953
1953
|
* @param {Array} [amuletDisclosures=[]] - Pre-fetched Amulet disclosures (required when using a provider). Must contain AmuletRules, OpenMiningRound, and ExternalPartyAmuletRules.
|
|
1954
1954
|
* @returns {Promise<Object|null>} Merge result data, or null on failure
|
|
@@ -1961,7 +1961,7 @@ export async function mergeAmuletHoldingsForParty(party, returnCommand = false,
|
|
|
1961
1961
|
return { error: "amuletDisclosures are required when using a provider for Amulet merge" };
|
|
1962
1962
|
}
|
|
1963
1963
|
returnCommand = true;
|
|
1964
|
-
// Wallet providers
|
|
1964
|
+
// Wallet providers commonly have a ~100 contract limit per transaction.
|
|
1965
1965
|
if (!maxUtxos) {
|
|
1966
1966
|
maxUtxos = 100;
|
|
1967
1967
|
}
|
|
@@ -2171,7 +2171,7 @@ export async function mergeAmuletHoldingsForParty(party, returnCommand = false,
|
|
|
2171
2171
|
* @param {string} party - The party ID
|
|
2172
2172
|
* @param {string} utilityAsset - The utility asset ID (e.g., "USDCx", "CBTC")
|
|
2173
2173
|
* @param {boolean} [returnCommand=false] - If true, returns the raw command/endpoint instead of executing. Forced to true when provider is set.
|
|
2174
|
-
* @param {Object} [provider=null] - Wallet provider
|
|
2174
|
+
* @param {Object} [provider=null] - Wallet provider with getActiveContracts(). When set, skips ledger API calls and returns the command for the wallet to sign.
|
|
2175
2175
|
* @param {number} [maxUtxos=null] - Maximum number of UTXOs to merge. When set, picks the smallest holdings first.
|
|
2176
2176
|
* @returns {Promise<Object|null>} Merge result data, or {command, endpoint} when returnCommand is true, or null on failure
|
|
2177
2177
|
*/
|
|
@@ -2180,7 +2180,7 @@ export async function mergeUtilityHoldingsForParty(party, utilityAsset, returnCo
|
|
|
2180
2180
|
provider = resolveProvider(provider);
|
|
2181
2181
|
if (provider) {
|
|
2182
2182
|
returnCommand = true;
|
|
2183
|
-
// Wallet providers
|
|
2183
|
+
// Wallet providers commonly have a ~100 contract limit per transaction.
|
|
2184
2184
|
// Default to 100 when no explicit maxUtxos is set.
|
|
2185
2185
|
if (!maxUtxos) {
|
|
2186
2186
|
maxUtxos = 100;
|
|
@@ -2656,7 +2656,7 @@ export { finalizeWithdrawFunds, withdrawFunds, withdrawDelegation } from "../../
|
|
|
2656
2656
|
export async function buildAllocationWithdrawCommand(opts) {
|
|
2657
2657
|
const { disclosures, userId } = opts || {};
|
|
2658
2658
|
const assetId = normalizeAssetId(opts.assetId);
|
|
2659
|
-
const sender = getAdapterPartyId() || opts.sender || config.VALIDATOR_USER_PARTY_ID;
|
|
2659
|
+
const sender = (await getAdapterPartyId()) || opts.sender || config.VALIDATOR_USER_PARTY_ID;
|
|
2660
2660
|
|
|
2661
2661
|
if (!opts.allocationCids || !sender || !assetId) {
|
|
2662
2662
|
return { error: "buildAllocationWithdrawCommand: allocationCids, sender, and assetId are required" };
|
|
@@ -2848,7 +2848,7 @@ export async function buildAllocationWithdrawCommand(opts) {
|
|
|
2848
2848
|
* @returns {Promise<Object>} Ledger API response, or { error } on failure.
|
|
2849
2849
|
*/
|
|
2850
2850
|
export async function onboardUser(user = {}, returnCommand = false) {
|
|
2851
|
-
user.partyId = user.partyId ?? getAdapterPartyId() ?? config.VALIDATOR_USER_PARTY_ID;
|
|
2851
|
+
user.partyId = user.partyId ?? (await getAdapterPartyId()) ?? config.VALIDATOR_USER_PARTY_ID;
|
|
2852
2852
|
user.userId = user.userId ?? getUserId() ?? config.AUTH0_USER_ID ?? "temple";
|
|
2853
2853
|
if (!user.partyId) {
|
|
2854
2854
|
const msg = "onboardUser: user party is required. Pass it directly, set WALLET_ADAPTER, or configure VALIDATOR_USER_PARTY_ID.";
|
|
@@ -3031,7 +3031,7 @@ export async function getUserBalances(party = null, provider = null) {
|
|
|
3031
3031
|
console.error(msg);
|
|
3032
3032
|
return { error: msg };
|
|
3033
3033
|
}
|
|
3034
|
-
party = party ?? getAdapterPartyId() ?? config.VALIDATOR_USER_PARTY_ID;
|
|
3034
|
+
party = party ?? (await getAdapterPartyId()) ?? config.VALIDATOR_USER_PARTY_ID;
|
|
3035
3035
|
if (!party) {
|
|
3036
3036
|
return { error: "Party ID is required. Pass it directly, connect a wallet adapter, or configure VALIDATOR_USER_PARTY_ID." };
|
|
3037
3037
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Universal Wallet Adapter contract.
|
|
3
3
|
*
|
|
4
|
-
* Every wallet
|
|
4
|
+
* Every wallet provider is
|
|
5
5
|
* represented as a *normalized adapter* implementing the capability interface
|
|
6
6
|
* defined here. The rest of the SDK never talks to a wallet/provider SDK
|
|
7
7
|
* directly — it goes through the wallet service (./service.js), which dispatches
|
|
@@ -26,14 +26,14 @@
|
|
|
26
26
|
|
|
27
27
|
/** A normalized wallet adapter produced by {@link defineWalletAdapter}. */
|
|
28
28
|
export interface WalletAdapter {
|
|
29
|
-
/** Provider id, e.g. "loop". */
|
|
29
|
+
/** Provider id, e.g. "loop" or "console". */
|
|
30
30
|
readonly id: string;
|
|
31
31
|
/** True for server-side adapters that sign/submit locally. */
|
|
32
32
|
readonly isServer: boolean;
|
|
33
33
|
|
|
34
34
|
// ── Required capabilities ──
|
|
35
|
-
/** Resolve the wallet's primary party id. */
|
|
36
|
-
getPartyId(): string | null
|
|
35
|
+
/** Resolve the wallet's primary party id. May resolve asynchronously. */
|
|
36
|
+
getPartyId(): Promise<string | null>;
|
|
37
37
|
/** Read active contracts matching `args` via the wallet. */
|
|
38
38
|
getActiveContracts(args: unknown): Promise<unknown>;
|
|
39
39
|
/** Sign and submit a ledger command via the wallet. */
|
|
@@ -59,7 +59,7 @@ export interface WalletAdapter {
|
|
|
59
59
|
export interface WalletAdapterDefinition {
|
|
60
60
|
id?: string;
|
|
61
61
|
isServer?: boolean;
|
|
62
|
-
getPartyId(): string | null
|
|
62
|
+
getPartyId(): string | null | Promise<string | null>;
|
|
63
63
|
getActiveContracts(args: unknown): Promise<unknown> | unknown;
|
|
64
64
|
submitCommand(command: unknown): Promise<unknown> | unknown;
|
|
65
65
|
payDueGasIfAny?(): Promise<void> | void;
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import config from "../../../src/config/index.js";
|
|
2
|
+
import { defineWalletAdapter, type WalletAdapter } from "./adapter.js";
|
|
3
|
+
|
|
4
|
+
type ConsoleNetworkVariant = "CANTON_NETWORK_DEV" | "CANTON_NETWORK_TEST" | "CANTON_NETWORK";
|
|
5
|
+
|
|
6
|
+
export interface ConsoleWalletAdapterOptions {
|
|
7
|
+
/** Console network id. Defaults from config.NETWORK when omitted. */
|
|
8
|
+
network?: ConsoleNetworkVariant | "localhost" | "testnet" | "mainnet" | string;
|
|
9
|
+
/** Optional party id seed for SDK call sites that need a synchronous party. */
|
|
10
|
+
partyId?: string;
|
|
11
|
+
/** Optional explicit read parties. Defaults to the active Console account party. */
|
|
12
|
+
parties?: string[];
|
|
13
|
+
/** Use prepareExecuteAndWait when available. Defaults to true. */
|
|
14
|
+
waitForExecution?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ConsoleWalletAccount {
|
|
18
|
+
partyId?: string | null;
|
|
19
|
+
networkId?: string | null;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface ConsoleContractsRequest {
|
|
24
|
+
network: ConsoleNetworkVariant | string;
|
|
25
|
+
parties: string[];
|
|
26
|
+
templateIds: string[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface ConsoleWalletLike {
|
|
30
|
+
getPrimaryAccount: () => Promise<ConsoleWalletAccount | undefined> | ConsoleWalletAccount | undefined;
|
|
31
|
+
getContracts: (data: ConsoleContractsRequest) => Promise<unknown> | unknown;
|
|
32
|
+
prepareExecute?: (data: ConsoleExecuteRequest) => Promise<unknown> | unknown;
|
|
33
|
+
prepareExecuteAndWait?: (data: ConsoleExecuteRequest) => Promise<unknown> | unknown;
|
|
34
|
+
disconnect?: () => Promise<void> | void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface ConsoleExecuteRequest {
|
|
38
|
+
actAs?: string[];
|
|
39
|
+
commandId?: string;
|
|
40
|
+
commands: unknown[];
|
|
41
|
+
disclosedContracts?: unknown[];
|
|
42
|
+
packageIdSelectionPreference?: string[];
|
|
43
|
+
readAs?: string[];
|
|
44
|
+
synchronizerId?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function hasConsoleSubmitCapability(value: Record<string, unknown>): boolean {
|
|
48
|
+
return typeof value.prepareExecute === "function" || typeof value.prepareExecuteAndWait === "function";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
52
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function isPromiseLike<T>(value: unknown): value is PromiseLike<T> {
|
|
56
|
+
return isRecord(value) && typeof value.then === "function";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function asStringArray(value: unknown): string[] {
|
|
60
|
+
if (Array.isArray(value)) return value.filter((entry): entry is string => typeof entry === "string" && entry.length > 0);
|
|
61
|
+
if (typeof value === "string" && value.length > 0) return [value];
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function firstString(...values: unknown[]): string | undefined {
|
|
66
|
+
for (const value of values) {
|
|
67
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function firstRecord(...values: unknown[]): Record<string, unknown> | undefined {
|
|
73
|
+
for (const value of values) {
|
|
74
|
+
if (isRecord(value)) return value;
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function resolveConsoleWallet(input: unknown): ConsoleWalletLike {
|
|
80
|
+
const candidate = isRecord(input) && isRecord(input.consoleWallet) ? input.consoleWallet : input;
|
|
81
|
+
if (!isRecord(candidate)) {
|
|
82
|
+
throw new Error("[Temple SDK] createConsoleWalletAdapter requires a Console wallet SDK instance.");
|
|
83
|
+
}
|
|
84
|
+
if (typeof candidate.getPrimaryAccount !== "function" || typeof candidate.getContracts !== "function") {
|
|
85
|
+
throw new Error("[Temple SDK] Console wallet SDK must expose getPrimaryAccount() and getContracts().");
|
|
86
|
+
}
|
|
87
|
+
if (!hasConsoleSubmitCapability(candidate)) {
|
|
88
|
+
throw new Error("[Temple SDK] Console wallet SDK must expose prepareExecute() or prepareExecuteAndWait().");
|
|
89
|
+
}
|
|
90
|
+
return candidate as unknown as ConsoleWalletLike;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function isConsoleWalletLike(value: unknown): boolean {
|
|
94
|
+
const candidate = isRecord(value) && isRecord(value.consoleWallet) ? value.consoleWallet : value;
|
|
95
|
+
return isRecord(candidate) && typeof candidate.getPrimaryAccount === "function" && typeof candidate.getContracts === "function" && hasConsoleSubmitCapability(candidate);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function resolveNetwork(network: ConsoleWalletAdapterOptions["network"]): ConsoleNetworkVariant | string {
|
|
99
|
+
const configured = String(network || config.NETWORK || "").toLowerCase();
|
|
100
|
+
switch (configured) {
|
|
101
|
+
case "localhost":
|
|
102
|
+
case "local":
|
|
103
|
+
case "dev":
|
|
104
|
+
case "devnet":
|
|
105
|
+
return "CANTON_NETWORK_DEV";
|
|
106
|
+
case "testnet":
|
|
107
|
+
case "test":
|
|
108
|
+
return "CANTON_NETWORK_TEST";
|
|
109
|
+
case "mainnet":
|
|
110
|
+
case "main":
|
|
111
|
+
return "CANTON_NETWORK";
|
|
112
|
+
default:
|
|
113
|
+
return network || "CANTON_NETWORK";
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function extractPartyId(account: ConsoleWalletAccount | undefined): string | null {
|
|
118
|
+
return typeof account?.partyId === "string" && account.partyId ? account.partyId : null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function extractTemplateIds(args: unknown): string[] {
|
|
122
|
+
if (!isRecord(args)) return [];
|
|
123
|
+
const direct = [...asStringArray(args.templateIds), ...asStringArray(args.templateId)];
|
|
124
|
+
if (direct.length > 0) return direct;
|
|
125
|
+
|
|
126
|
+
const filter = firstRecord(args.filter);
|
|
127
|
+
const filtersByParty = firstRecord(filter?.filtersByParty);
|
|
128
|
+
const templateIds: string[] = [];
|
|
129
|
+
for (const partyFilter of Object.values(filtersByParty || {})) {
|
|
130
|
+
const cumulative = firstRecord(partyFilter)?.cumulative;
|
|
131
|
+
if (!Array.isArray(cumulative)) continue;
|
|
132
|
+
for (const entry of cumulative) {
|
|
133
|
+
const identifierFilter = firstRecord(entry)?.identifierFilter;
|
|
134
|
+
const templateFilter = firstRecord(firstRecord(identifierFilter)?.["TemplateFilter"])?.value;
|
|
135
|
+
templateIds.push(...asStringArray(firstRecord(templateFilter)?.templateId));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return templateIds;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function extractParties(args: unknown, fallbackParty: string | null, optionParties: string[] | undefined): string[] {
|
|
142
|
+
if (optionParties?.length) return optionParties;
|
|
143
|
+
if (isRecord(args)) {
|
|
144
|
+
const direct = [...asStringArray(args.parties), ...asStringArray(args.party)];
|
|
145
|
+
if (direct.length > 0) return direct;
|
|
146
|
+
const filtersByParty = firstRecord(firstRecord(args.filter)?.filtersByParty);
|
|
147
|
+
const filteredParties = Object.keys(filtersByParty || {});
|
|
148
|
+
if (filteredParties.length > 0) return filteredParties;
|
|
149
|
+
}
|
|
150
|
+
return fallbackParty ? [fallbackParty] : [];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function unwrapContractItems(response: unknown): unknown[] {
|
|
154
|
+
if (Array.isArray(response)) return response;
|
|
155
|
+
if (!isRecord(response)) return [];
|
|
156
|
+
for (const key of ["items", "activeContracts", "contracts", "result"]) {
|
|
157
|
+
const value = response[key];
|
|
158
|
+
if (Array.isArray(value)) return value;
|
|
159
|
+
}
|
|
160
|
+
return [];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function normalizeContractItem(item: unknown): unknown | null {
|
|
164
|
+
if (!isRecord(item)) return null;
|
|
165
|
+
const contractEntry = firstRecord(item.contractEntry) || item;
|
|
166
|
+
const jsActive = firstRecord(contractEntry.JsActiveContract, contractEntry.jsActiveContract, contractEntry.activeContract) || contractEntry;
|
|
167
|
+
const createdEvent = firstRecord(jsActive.createdEvent, item.createdEvent, item.contract, jsActive) || {};
|
|
168
|
+
const createArgument = firstRecord(createdEvent.createArgument, createdEvent.create_argument, createdEvent.payload, item.payload) || {};
|
|
169
|
+
const contractId = firstString(createdEvent.contractId, createdEvent.contract_id, item.contractId, item.contract_id);
|
|
170
|
+
const templateId = firstString(createdEvent.templateId, createdEvent.template_id, jsActive.templateId, item.templateId, item.template_id);
|
|
171
|
+
const createdEventBlob = firstString(createdEvent.createdEventBlob, createdEvent.created_event_blob, createdEvent.eventBlob, item.createdEventBlob, item.created_event_blob, item.eventBlob);
|
|
172
|
+
const synchronizerId = firstString(jsActive.synchronizerId, jsActive.synchronizer_id, item.synchronizerId, item.synchronizer_id, item.domainId, item.domain_id);
|
|
173
|
+
|
|
174
|
+
if (!contractId && !templateId && !createdEventBlob) return null;
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
contractEntry: {
|
|
178
|
+
JsActiveContract: {
|
|
179
|
+
...jsActive,
|
|
180
|
+
createdEvent: {
|
|
181
|
+
...createdEvent,
|
|
182
|
+
contractId,
|
|
183
|
+
templateId,
|
|
184
|
+
createArgument,
|
|
185
|
+
createdEventBlob,
|
|
186
|
+
},
|
|
187
|
+
synchronizerId,
|
|
188
|
+
templateId,
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function normalizeContractsResponse(response: unknown): unknown[] {
|
|
195
|
+
return unwrapContractItems(response)
|
|
196
|
+
.map(normalizeContractItem)
|
|
197
|
+
.filter((entry): entry is unknown => entry !== null);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function extractErrorDetail(error: unknown): string {
|
|
201
|
+
if (!isRecord(error)) return String(error);
|
|
202
|
+
const response = isRecord(error.response) ? error.response : undefined;
|
|
203
|
+
const data = response && response.data !== undefined ? response.data : undefined;
|
|
204
|
+
if (typeof data === "string") return data;
|
|
205
|
+
if (isRecord(data)) return JSON.stringify(data);
|
|
206
|
+
if (typeof error.message === "string") return error.message;
|
|
207
|
+
return String(error);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function wrapConsoleSubmitError(error: unknown): Error {
|
|
211
|
+
const detail = extractErrorDetail(error);
|
|
212
|
+
return new Error(`[Temple SDK] Console wallet submit failed: ${detail}.`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function normalizeLedgerCommand(command: unknown): Record<string, unknown> {
|
|
216
|
+
if (!isRecord(command) || !Array.isArray(command.commands)) {
|
|
217
|
+
throw new Error("[Temple SDK] Console wallet submitCommand() expects a ledger command with a commands array.");
|
|
218
|
+
}
|
|
219
|
+
return command;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function createConsoleWalletAdapter(consoleWallet: unknown, options: ConsoleWalletAdapterOptions = {}): WalletAdapter {
|
|
223
|
+
const wallet = resolveConsoleWallet(consoleWallet);
|
|
224
|
+
let cachedPartyId: string | null = options.partyId || null;
|
|
225
|
+
let pendingPartyId: Promise<string | null> | null = null;
|
|
226
|
+
|
|
227
|
+
const loadPartyId = async (): Promise<string | null> => {
|
|
228
|
+
const account = await wallet.getPrimaryAccount();
|
|
229
|
+
cachedPartyId = extractPartyId(account);
|
|
230
|
+
pendingPartyId = null;
|
|
231
|
+
return cachedPartyId;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const ensurePartyId = async (): Promise<string | null> => {
|
|
235
|
+
if (cachedPartyId) return cachedPartyId;
|
|
236
|
+
if (!pendingPartyId) pendingPartyId = loadPartyId();
|
|
237
|
+
return pendingPartyId;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
return defineWalletAdapter({
|
|
241
|
+
id: "console",
|
|
242
|
+
isServer: false,
|
|
243
|
+
getRawProvider: () => wallet,
|
|
244
|
+
getPartyId: ensurePartyId,
|
|
245
|
+
|
|
246
|
+
getActiveContracts: async (args) => {
|
|
247
|
+
const partyId = await ensurePartyId();
|
|
248
|
+
const templateIds = extractTemplateIds(args);
|
|
249
|
+
const parties = extractParties(args, partyId, options.parties);
|
|
250
|
+
if (templateIds.length === 0) {
|
|
251
|
+
throw new Error("[Temple SDK] Console wallet getActiveContracts() requires at least one templateId.");
|
|
252
|
+
}
|
|
253
|
+
if (parties.length === 0) {
|
|
254
|
+
throw new Error("[Temple SDK] Console wallet getActiveContracts() requires a party id from getPrimaryAccount() or adapter options.");
|
|
255
|
+
}
|
|
256
|
+
const response = await wallet.getContracts({
|
|
257
|
+
network: resolveNetwork(options.network),
|
|
258
|
+
parties,
|
|
259
|
+
templateIds,
|
|
260
|
+
});
|
|
261
|
+
return normalizeContractsResponse(response);
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
submitCommand: async (command) => {
|
|
265
|
+
// resolveConsoleWallet() guarantees at least one prepare method exists.
|
|
266
|
+
const prepareRequest = normalizeLedgerCommand(command) as unknown as ConsoleExecuteRequest;
|
|
267
|
+
const useWait =
|
|
268
|
+
typeof wallet.prepareExecuteAndWait === "function" &&
|
|
269
|
+
(options.waitForExecution !== false || typeof wallet.prepareExecute !== "function");
|
|
270
|
+
try {
|
|
271
|
+
return await (useWait ? wallet.prepareExecuteAndWait!(prepareRequest) : wallet.prepareExecute!(prepareRequest));
|
|
272
|
+
} catch (error) {
|
|
273
|
+
throw wrapConsoleSubmitError(error);
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
disconnect: async () => {
|
|
278
|
+
if (typeof wallet.disconnect === "function") await wallet.disconnect();
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
}
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
|
|
18
18
|
import { defineWalletAdapter, type WalletAdapter } from "./adapter.js";
|
|
19
19
|
|
|
20
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
21
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
22
|
+
}
|
|
23
|
+
|
|
20
24
|
/** The Loop read/submit provider sub-object (or the Loop instance itself). */
|
|
21
25
|
interface LoopProvider {
|
|
22
26
|
party_id?: string | null;
|
|
@@ -40,6 +44,18 @@ interface LoopLike extends LoopProvider {
|
|
|
40
44
|
payGas?: (trackingId: string) => Promise<unknown> | unknown;
|
|
41
45
|
}
|
|
42
46
|
|
|
47
|
+
export function isLoopWalletLike(value: unknown): boolean {
|
|
48
|
+
if (!isRecord(value)) return false;
|
|
49
|
+
const provider = isRecord(value.provider) ? value.provider : value;
|
|
50
|
+
return (
|
|
51
|
+
typeof provider.getActiveContracts === "function" &&
|
|
52
|
+
(typeof value.executeTransaction === "function" ||
|
|
53
|
+
typeof provider.submitTransaction === "function" ||
|
|
54
|
+
isRecord(value.session) ||
|
|
55
|
+
typeof provider.party_id === "string")
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
43
59
|
/**
|
|
44
60
|
* Detect whether a Loop instance is server-side.
|
|
45
61
|
* Loop-specific: server-side has null connection.ticketId and connection.ws.
|
|
@@ -59,6 +75,9 @@ export function createLoopWalletAdapter(loop: unknown): WalletAdapter {
|
|
|
59
75
|
if (!loop || typeof loop !== "object") {
|
|
60
76
|
throw new Error("[Temple SDK] createLoopWalletAdapter requires a Loop wallet instance.");
|
|
61
77
|
}
|
|
78
|
+
if (!isLoopWalletLike(loop)) {
|
|
79
|
+
throw new Error("[Temple SDK] createLoopWalletAdapter received an unsupported Loop wallet instance.");
|
|
80
|
+
}
|
|
62
81
|
|
|
63
82
|
const sdk = loop as LoopLike;
|
|
64
83
|
const isServer = detectServerSide(sdk);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isWalletAdapter, type WalletAdapter } from "./adapter.js";
|
|
2
|
+
import { createConsoleWalletAdapter, isConsoleWalletLike } from "./console.js";
|
|
3
|
+
import { createLoopWalletAdapter, isLoopWalletLike } from "./loop.js";
|
|
4
|
+
|
|
5
|
+
type WalletAdapterFactory = {
|
|
6
|
+
id: string;
|
|
7
|
+
canWrap(value: unknown): boolean;
|
|
8
|
+
wrap(value: unknown): WalletAdapter;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const BUILT_IN_FACTORIES: WalletAdapterFactory[] = [
|
|
12
|
+
{ id: "console", canWrap: isConsoleWalletLike, wrap: (value) => createConsoleWalletAdapter(value) },
|
|
13
|
+
{ id: "loop", canWrap: isLoopWalletLike, wrap: createLoopWalletAdapter },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export function normalizeWalletAdapter(adapter: unknown): WalletAdapter {
|
|
17
|
+
if (isWalletAdapter(adapter)) return adapter;
|
|
18
|
+
|
|
19
|
+
for (const factory of BUILT_IN_FACTORIES) {
|
|
20
|
+
if (factory.canWrap(adapter)) return factory.wrap(adapter);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
throw new Error(
|
|
24
|
+
"[Temple SDK] Unsupported wallet adapter. Pass a normalized adapter from createLoopWalletAdapter(), createConsoleWalletAdapter(), or defineWalletAdapter().",
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -47,7 +47,7 @@ function requireAdapter(): WalletAdapter {
|
|
|
47
47
|
// ── Required capabilities ──────────────────────────────────────────────────
|
|
48
48
|
|
|
49
49
|
/** Resolve the active wallet's party id. Throws when no adapter is configured. */
|
|
50
|
-
export function getPartyId(): string | null {
|
|
50
|
+
export function getPartyId(): Promise<string | null> {
|
|
51
51
|
return requireAdapter().getPartyId();
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Backward-compatible public surface for wallet interactions. The real wallet
|
|
5
5
|
* architecture lives in ./wallet/ — a universal adapter contract (adapter.ts),
|
|
6
6
|
* a service registry that dispatches capability calls (service.ts), and one
|
|
7
|
-
* factory per wallet
|
|
7
|
+
* factory per wallet provider. This module is a thin
|
|
8
8
|
* facade over that service so existing imports keep working unchanged.
|
|
9
9
|
*
|
|
10
10
|
* Adding a new wallet does not touch this file: write a create<Name>WalletAdapter()
|
|
@@ -17,20 +17,21 @@ import {
|
|
|
17
17
|
submitCommand as serviceSubmitCommand,
|
|
18
18
|
payDueGasIfAny as servicePayDueGasIfAny,
|
|
19
19
|
} from "./wallet/service.js";
|
|
20
|
-
import {
|
|
21
|
-
import { createLoopWalletAdapter } from "./wallet/loop.js";
|
|
20
|
+
import { normalizeWalletAdapter } from "./wallet/registry.js";
|
|
22
21
|
import type { WalletAdapter } from "./wallet/adapter.js";
|
|
23
22
|
|
|
24
23
|
// Re-export the adapter toolkit so consumers can build/register custom wallets.
|
|
25
24
|
export { createLoopWalletAdapter } from "./wallet/loop.js";
|
|
25
|
+
export { createConsoleWalletAdapter } from "./wallet/console.js";
|
|
26
26
|
export { defineWalletAdapter, isWalletAdapter } from "./wallet/adapter.js";
|
|
27
27
|
export type { WalletAdapter, WalletAdapterDefinition } from "./wallet/adapter.js";
|
|
28
|
+
export type { ConsoleWalletAdapterOptions } from "./wallet/console.js";
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Set the active wallet adapter.
|
|
31
32
|
*
|
|
32
33
|
* Accepts either a normalized adapter (from a create*WalletAdapter() factory) or
|
|
33
|
-
* a raw
|
|
34
|
+
* a raw wallet instance recognized by a built-in wallet factory.
|
|
34
35
|
* Pass a falsy value to clear the adapter.
|
|
35
36
|
*/
|
|
36
37
|
export function setWalletAdapter(adapter: unknown): void {
|
|
@@ -38,8 +39,7 @@ export function setWalletAdapter(adapter: unknown): void {
|
|
|
38
39
|
setActiveAdapter(null);
|
|
39
40
|
return;
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
-
setActiveAdapter(normalized);
|
|
42
|
+
setActiveAdapter(normalizeWalletAdapter(adapter));
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
@@ -70,7 +70,7 @@ export function isServerMode(): boolean {
|
|
|
70
70
|
/**
|
|
71
71
|
* Get the party ID from the active wallet adapter, or null when none is set.
|
|
72
72
|
*/
|
|
73
|
-
export function getAdapterPartyId(): string | null {
|
|
73
|
+
export async function getAdapterPartyId(): Promise<string | null> {
|
|
74
74
|
const adapter = getActiveAdapter();
|
|
75
75
|
return adapter ? adapter.getPartyId() : null;
|
|
76
76
|
}
|
|
@@ -77,7 +77,7 @@ export async function finalizeWithdrawFunds(
|
|
|
77
77
|
): Promise<Record<string, unknown>> {
|
|
78
78
|
const { allocationId, sender: senderOpt, assetId: rawAssetId, disclosures, userId } = opts;
|
|
79
79
|
const assetId = normalizeAssetId(rawAssetId);
|
|
80
|
-
const sender = getAdapterPartyId() ?? senderOpt ?? config.VALIDATOR_USER_PARTY_ID;
|
|
80
|
+
const sender = (await getAdapterPartyId()) ?? senderOpt ?? config.VALIDATOR_USER_PARTY_ID;
|
|
81
81
|
|
|
82
82
|
if (!allocationId || !sender || !assetId) {
|
|
83
83
|
const msg = "finalizeWithdrawFunds: allocationId, sender, and assetId are required";
|
|
@@ -345,7 +345,7 @@ export async function withdrawFunds(
|
|
|
345
345
|
const { amount, pollIntervalMs = 2000, maxPollAttempts = 30 } = opts || {};
|
|
346
346
|
const asset_id = normalizeAssetId(opts?.asset_id);
|
|
347
347
|
|
|
348
|
-
const sender = getAdapterPartyId() ?? config.VALIDATOR_USER_PARTY_ID;
|
|
348
|
+
const sender = (await getAdapterPartyId()) ?? config.VALIDATOR_USER_PARTY_ID;
|
|
349
349
|
if (!sender) {
|
|
350
350
|
const msg = "withdrawFunds: sender party is required. Connect a wallet adapter or configure VALIDATOR_USER_PARTY_ID.";
|
|
351
351
|
console.error(msg);
|
|
@@ -440,7 +440,7 @@ export async function withdrawDelegation(
|
|
|
440
440
|
user: string | null = null,
|
|
441
441
|
returnCommand = false,
|
|
442
442
|
): Promise<Record<string, unknown>> {
|
|
443
|
-
let resolvedUser = user ?? getAdapterPartyId() ?? config.VALIDATOR_USER_PARTY_ID;
|
|
443
|
+
let resolvedUser = user ?? (await getAdapterPartyId()) ?? config.VALIDATOR_USER_PARTY_ID;
|
|
444
444
|
let resolvedDelegationId = delegationId;
|
|
445
445
|
|
|
446
446
|
// If no delegationId passed, fetch it from the API
|
package/src/config/index.d.ts
CHANGED
|
@@ -20,6 +20,13 @@ export function setWalletAdapter(adapter: any): void;
|
|
|
20
20
|
export function getWalletAdapter(): any;
|
|
21
21
|
export function getAdapterProvider(): any;
|
|
22
22
|
export function createLoopWalletAdapter(loop: any): any;
|
|
23
|
+
export interface ConsoleWalletAdapterOptions {
|
|
24
|
+
network?: string;
|
|
25
|
+
partyId?: string;
|
|
26
|
+
parties?: string[];
|
|
27
|
+
waitForExecution?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export function createConsoleWalletAdapter(consoleWallet: any, options?: ConsoleWalletAdapterOptions): any;
|
|
23
30
|
export function defineWalletAdapter(definition: any): any;
|
|
24
31
|
export function isWalletAdapter(value: any): boolean;
|
|
25
32
|
export const NETWORK_LOCALHOST: "localhost";
|