@empereur-rouge/pms-sdk 0.3.7 → 0.5.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/dist/index.cjs +287 -101
- package/dist/index.d.cts +394 -123
- package/dist/index.d.ts +394 -123
- package/dist/index.js +279 -100
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import { wordlist } from "@scure/bip39/wordlists/english";
|
|
|
9
9
|
// src/utils.ts
|
|
10
10
|
import { sha256 } from "@noble/hashes/sha2";
|
|
11
11
|
import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
|
|
12
|
+
import { base64, bech32m } from "@scure/base";
|
|
12
13
|
function sha256Hash(data) {
|
|
13
14
|
return sha256(data);
|
|
14
15
|
}
|
|
@@ -21,12 +22,103 @@ function fromHex(hex) {
|
|
|
21
22
|
function encodeUtf8(str) {
|
|
22
23
|
return new TextEncoder().encode(str);
|
|
23
24
|
}
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
25
|
+
function toBase64(bytes) {
|
|
26
|
+
return base64.encode(bytes);
|
|
27
|
+
}
|
|
28
|
+
function txSigningMessage(networkId, inputs, outputs, fee) {
|
|
29
|
+
const canonInputs = inputs.map((i) => ({
|
|
30
|
+
out: { txid: i.out.txid, index: i.out.index }
|
|
31
|
+
}));
|
|
32
|
+
const canonOutputs = outputs.map((o) => {
|
|
33
|
+
const out = {
|
|
34
|
+
address: o.address,
|
|
35
|
+
amount: o.amount
|
|
36
|
+
};
|
|
37
|
+
if (o.asset_id !== void 0 && o.asset_id !== null) {
|
|
38
|
+
out.asset_id = o.asset_id;
|
|
39
|
+
}
|
|
40
|
+
if (o.locked_until !== void 0 && o.locked_until !== null) {
|
|
41
|
+
out.locked_until = o.locked_until;
|
|
42
|
+
}
|
|
43
|
+
if (o.spend_condition !== void 0 && o.spend_condition !== null) {
|
|
44
|
+
out.spend_condition = o.spend_condition;
|
|
45
|
+
}
|
|
46
|
+
if (o.created_at !== void 0 && o.created_at !== null) {
|
|
47
|
+
out.created_at = o.created_at;
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
});
|
|
51
|
+
const canon = {
|
|
52
|
+
network_id: networkId,
|
|
53
|
+
inputs: canonInputs,
|
|
54
|
+
outputs: canonOutputs,
|
|
55
|
+
fee
|
|
56
|
+
};
|
|
57
|
+
return toHex(sha256Hash(encodeUtf8(JSON.stringify(canon))));
|
|
58
|
+
}
|
|
59
|
+
var PLAIN_VARIANT_TO_PAYLOAD_TYPE = {
|
|
60
|
+
Genesis: "Genesis",
|
|
61
|
+
Mint: "Mint",
|
|
62
|
+
TxUtxo: "Transaction",
|
|
63
|
+
Milestone: "Milestone",
|
|
64
|
+
Nft: "Nft",
|
|
65
|
+
ConfigUpdate: "ConfigUpdate",
|
|
66
|
+
Reward: "Reward",
|
|
67
|
+
EncryptedReward: "EncryptedReward",
|
|
68
|
+
TokenCreate: "TokenCreate",
|
|
69
|
+
BridgeLock: "BridgeLock",
|
|
70
|
+
BridgeMint: "BridgeMint",
|
|
71
|
+
Freeze: "Freeze",
|
|
72
|
+
Unfreeze: "Unfreeze",
|
|
73
|
+
Seize: "Seize",
|
|
74
|
+
Reverse: "Reverse",
|
|
75
|
+
ContractRegister: "ContractRegister",
|
|
76
|
+
ContractUpdate: "ContractUpdate",
|
|
77
|
+
LedgerOwnershipTransfer: "LedgerOwnershipTransfer",
|
|
78
|
+
CoordinatorKeyRotate: "CoordinatorKeyRotate"
|
|
79
|
+
};
|
|
80
|
+
var EMPTY_COMMITMENT = "0000000000000000000000000000000000000000000000000000000000000000";
|
|
81
|
+
function computeBlockId(parents, payload, nonce) {
|
|
82
|
+
let payload_type;
|
|
83
|
+
let commitment;
|
|
84
|
+
let len_hint;
|
|
85
|
+
let key_version;
|
|
86
|
+
if (payload === void 0 || payload === null) {
|
|
87
|
+
payload_type = "None";
|
|
88
|
+
commitment = EMPTY_COMMITMENT;
|
|
89
|
+
len_hint = 0;
|
|
90
|
+
key_version = 0;
|
|
91
|
+
} else if ("Plain" in payload) {
|
|
92
|
+
const plain = payload.Plain;
|
|
93
|
+
const variant = typeof plain === "string" ? plain : Object.keys(plain)[0];
|
|
94
|
+
payload_type = PLAIN_VARIANT_TO_PAYLOAD_TYPE[variant] ?? variant;
|
|
95
|
+
const plainBytes = encodeUtf8(JSON.stringify(plain));
|
|
96
|
+
commitment = toHex(sha256Hash(plainBytes));
|
|
97
|
+
len_hint = plainBytes.length;
|
|
98
|
+
key_version = 0;
|
|
99
|
+
} else {
|
|
100
|
+
const enc = payload.Encrypted;
|
|
101
|
+
payload_type = "Encrypted";
|
|
102
|
+
commitment = enc.commitment;
|
|
103
|
+
len_hint = enc.ciphertext_b64.length;
|
|
104
|
+
key_version = enc.key_version;
|
|
105
|
+
}
|
|
106
|
+
const head = {
|
|
107
|
+
parents,
|
|
108
|
+
nonce,
|
|
109
|
+
envelope: { payload_type, commitment, len_hint, key_version }
|
|
110
|
+
};
|
|
111
|
+
return toHex(sha256Hash(encodeUtf8(JSON.stringify(head))));
|
|
112
|
+
}
|
|
113
|
+
function x25519FromAddress(address) {
|
|
114
|
+
try {
|
|
115
|
+
const decoded = bech32m.decode(address, false);
|
|
116
|
+
const bytes = bech32m.fromWords(decoded.words);
|
|
117
|
+
if (bytes.length !== 52) return void 0;
|
|
118
|
+
return toHex(bytes.slice(20));
|
|
119
|
+
} catch {
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
30
122
|
}
|
|
31
123
|
function parseAmount(amount) {
|
|
32
124
|
const [whole, frac = ""] = amount.split(".");
|
|
@@ -39,6 +131,47 @@ function formatAmount(sats) {
|
|
|
39
131
|
const fracStr = frac.toString().padStart(8, "0");
|
|
40
132
|
return `${whole}.${fracStr}`;
|
|
41
133
|
}
|
|
134
|
+
var DAY_MS = 864e5;
|
|
135
|
+
function multisigAddress(m, pubkeys) {
|
|
136
|
+
const normalized = pubkeys.map((pk) => {
|
|
137
|
+
const t = pk.trim();
|
|
138
|
+
return (t.startsWith("0x") ? t.slice(2) : t).toLowerCase();
|
|
139
|
+
}).sort();
|
|
140
|
+
const parts = [
|
|
141
|
+
encodeUtf8("pms-multisig-v1"),
|
|
142
|
+
new Uint8Array([m, normalized.length]),
|
|
143
|
+
...normalized.map((pk) => encodeUtf8(pk))
|
|
144
|
+
];
|
|
145
|
+
const total = parts.reduce((n, p) => n + p.length, 0);
|
|
146
|
+
const buf = new Uint8Array(total);
|
|
147
|
+
let off = 0;
|
|
148
|
+
for (const p of parts) {
|
|
149
|
+
buf.set(p, off);
|
|
150
|
+
off += p.length;
|
|
151
|
+
}
|
|
152
|
+
return `msig1${toHex(sha256Hash(buf).slice(0, 20))}`;
|
|
153
|
+
}
|
|
154
|
+
function hashlockHash(preimage) {
|
|
155
|
+
const bytes = typeof preimage === "string" ? encodeUtf8(preimage) : preimage;
|
|
156
|
+
return toHex(sha256Hash(bytes));
|
|
157
|
+
}
|
|
158
|
+
function effectiveValue(amount, createdAtMs, nowMs, bpsPerDay) {
|
|
159
|
+
if (createdAtMs === void 0 || createdAtMs === null || !bpsPerDay) {
|
|
160
|
+
return amount;
|
|
161
|
+
}
|
|
162
|
+
const elapsed = nowMs - createdAtMs;
|
|
163
|
+
const days = elapsed > 0 ? BigInt(Math.floor(elapsed / DAY_MS)) : 0n;
|
|
164
|
+
if (days === 0n) return amount;
|
|
165
|
+
const sats = parseAmount(amount);
|
|
166
|
+
const scaled = sats * 10000n - sats * BigInt(bpsPerDay) * days;
|
|
167
|
+
if (scaled <= 0n) return "0.00000000";
|
|
168
|
+
return formatAmount(scaled / 10000n);
|
|
169
|
+
}
|
|
170
|
+
function spendableUtxos(utxos, nowMs = Date.now()) {
|
|
171
|
+
return utxos.filter(
|
|
172
|
+
(u) => u.locked_until === void 0 || u.locked_until === null || u.locked_until <= nowMs
|
|
173
|
+
);
|
|
174
|
+
}
|
|
42
175
|
|
|
43
176
|
// src/wallet.ts
|
|
44
177
|
var PmsWallet = class _PmsWallet {
|
|
@@ -213,11 +346,33 @@ var PmsWallet = class _PmsWallet {
|
|
|
213
346
|
function isValidMnemonic(mnemonic) {
|
|
214
347
|
return validateMnemonic(mnemonic.trim().toLowerCase(), wordlist);
|
|
215
348
|
}
|
|
349
|
+
function makeUnlock(signers, txHashHex, opts) {
|
|
350
|
+
if (signers.length === 0) {
|
|
351
|
+
throw new Error("makeUnlock: at least one signer is required");
|
|
352
|
+
}
|
|
353
|
+
const msg = encodeUtf8(txHashHex);
|
|
354
|
+
const sign = (w) => toBase64(fromHex(w.sign(msg)));
|
|
355
|
+
const [primary, ...rest] = signers;
|
|
356
|
+
const unlock = {
|
|
357
|
+
pubkey_hex: primary.publicKeyHex,
|
|
358
|
+
signature_b64: sign(primary)
|
|
359
|
+
};
|
|
360
|
+
if (rest.length > 0) {
|
|
361
|
+
unlock.cosigners = rest.map((w) => ({
|
|
362
|
+
pubkey_hex: w.publicKeyHex,
|
|
363
|
+
signature_b64: sign(w)
|
|
364
|
+
}));
|
|
365
|
+
}
|
|
366
|
+
if (opts?.preimageHex !== void 0) {
|
|
367
|
+
unlock.preimage_hex = opts.preimageHex;
|
|
368
|
+
}
|
|
369
|
+
return unlock;
|
|
370
|
+
}
|
|
216
371
|
|
|
217
372
|
// src/types.ts
|
|
218
373
|
var DEFAULT_CONFIG = {
|
|
219
374
|
networkId: "pms-mainnet",
|
|
220
|
-
protocolVersion:
|
|
375
|
+
protocolVersion: 3,
|
|
221
376
|
timeout: 3e4,
|
|
222
377
|
seedNodes: [],
|
|
223
378
|
enableRacing: true,
|
|
@@ -232,13 +387,13 @@ import { gcm } from "@noble/ciphers/aes.js";
|
|
|
232
387
|
import { hkdf as hkdf2 } from "@noble/hashes/hkdf";
|
|
233
388
|
import { sha256 as sha2563 } from "@noble/hashes/sha2";
|
|
234
389
|
import { randomBytes, bytesToHex as bytesToHex2, hexToBytes as hexToBytes2 } from "@noble/hashes/utils";
|
|
235
|
-
import { base64 } from "@scure/base";
|
|
390
|
+
import { base64 as base642 } from "@scure/base";
|
|
236
391
|
var SCHEME = "x25519+aes256gcm";
|
|
237
392
|
var HKDF_SALT = new TextEncoder().encode("pms-dek-wrap");
|
|
238
393
|
var HKDF_INFO_KEK = new TextEncoder().encode("kek-v1");
|
|
239
394
|
var HKDF_INFO_KID = new TextEncoder().encode("kid-v1");
|
|
240
395
|
function fromBase64(str) {
|
|
241
|
-
return
|
|
396
|
+
return base642.decode(str);
|
|
242
397
|
}
|
|
243
398
|
function sha256Hex(data) {
|
|
244
399
|
return bytesToHex2(sha2563(data));
|
|
@@ -403,11 +558,24 @@ var PmsClient = class {
|
|
|
403
558
|
}
|
|
404
559
|
/**
|
|
405
560
|
* Récupère les UTXOs d'une adresse.
|
|
561
|
+
*
|
|
562
|
+
* Depuis dag-pms v0.10.0, chaque UTXO expose aussi ses contraintes de
|
|
563
|
+
* dépense : `locked_until` (time-lock), `spend_condition`
|
|
564
|
+
* (MultiSig/HashLock) et `created_at` (base du demurrage). Utiliser
|
|
565
|
+
* [`spendableUtxos`] pour exclure les UTXOs encore verrouillés avant
|
|
566
|
+
* toute sélection de coins côté client.
|
|
406
567
|
*/
|
|
407
568
|
async getUtxos(address) {
|
|
408
569
|
const res = await this.fetch(`/v1/wallet/${address}/utxos`, void 0, { idempotent: true });
|
|
409
570
|
return res.utxos ?? [];
|
|
410
571
|
}
|
|
572
|
+
/**
|
|
573
|
+
* Dernier snapshot de preuve de réserves ancré (protocole 2.6,
|
|
574
|
+
* `GET /v1/reserves/latest`). 404 si aucun snapshot n'a encore été ancré.
|
|
575
|
+
*/
|
|
576
|
+
async getLatestReserves() {
|
|
577
|
+
return this.fetch("/v1/reserves/latest", void 0, { idempotent: true });
|
|
578
|
+
}
|
|
411
579
|
// ═══════════════════════════════════════════════════════════════════════
|
|
412
580
|
// Wallet API (Custodial — Server-Side)
|
|
413
581
|
// ═══════════════════════════════════════════════════════════════════════
|
|
@@ -864,101 +1032,83 @@ var PmsClient = class {
|
|
|
864
1032
|
}
|
|
865
1033
|
/**
|
|
866
1034
|
* Envoie des tokens à une adresse.
|
|
867
|
-
*
|
|
1035
|
+
*
|
|
1036
|
+
* Flux aligné sur dag-pms v0.9.0 (single-writer + vérification des
|
|
1037
|
+
* signatures de transaction par l'engine) :
|
|
1038
|
+
* 1. `POST /v1/tx/prepare` — le serveur sélectionne les UTXOs et calcule
|
|
1039
|
+
* les frais.
|
|
1040
|
+
* 2. Vérification défensive côté client : l'output destinataire demandé
|
|
1041
|
+
* existe bien, et le `tx_hash` retourné correspond au message canonique
|
|
1042
|
+
* recalculé localement (`txSigningMessage`). On ne signe JAMAIS un hash
|
|
1043
|
+
* opaque non vérifié.
|
|
1044
|
+
* 3. Le wallet signe la TRANSACTION (unlocks) — pas le bloc. C'est le
|
|
1045
|
+
* serveur qui forge et signe le bloc (single-writer enforcement).
|
|
1046
|
+
* 4. `POST /v1/wallet/tx/send` avec la TX signée + les clés X25519 des
|
|
1047
|
+
* destinataires pour le chiffrement du payload.
|
|
1048
|
+
*
|
|
1049
|
+
* @param params.to - Adresse destinataire (Bech32m de préférence)
|
|
1050
|
+
* @param params.amount - Montant décimal (ex: "10.0")
|
|
1051
|
+
* @param params.wallet - Wallet signataire (propriétaire des UTXOs)
|
|
1052
|
+
* @param params.assetId - Asset ID optionnel (undefined = PMS natif)
|
|
1053
|
+
* @returns `{id, status, block_id}` — id du bloc forgé par le serveur
|
|
868
1054
|
*/
|
|
869
1055
|
async send(params) {
|
|
870
|
-
const { to, amount, wallet,
|
|
871
|
-
const
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
const amountSats = parseAmount(amount);
|
|
879
|
-
const variableFee = amountSats * feeRateBps / 10000n;
|
|
880
|
-
const fee = baseFeeSats + variableFee;
|
|
881
|
-
const totalNeeded = amountSats + fee;
|
|
882
|
-
let selectedSats = 0n;
|
|
883
|
-
const selectedUtxos = [];
|
|
884
|
-
for (const utxo of utxos) {
|
|
885
|
-
selectedUtxos.push(utxo);
|
|
886
|
-
selectedSats += parseAmount(utxo.amount || "0");
|
|
887
|
-
if (selectedSats >= totalNeeded) break;
|
|
1056
|
+
const { to, amount, wallet, assetId } = params;
|
|
1057
|
+
const prepareBody = {
|
|
1058
|
+
from: wallet.address,
|
|
1059
|
+
to,
|
|
1060
|
+
amount
|
|
1061
|
+
};
|
|
1062
|
+
if (assetId !== void 0) {
|
|
1063
|
+
prepareBody.asset_id = assetId;
|
|
888
1064
|
}
|
|
889
|
-
|
|
1065
|
+
const prepared = await this.prepareTx(prepareBody);
|
|
1066
|
+
const { unsigned_tx, tx_hash } = prepared;
|
|
1067
|
+
const requestedSats = parseAmount(amount);
|
|
1068
|
+
const recipientOutput = unsigned_tx.outputs.find(
|
|
1069
|
+
(o) => o.address === to && (o.asset_id ?? void 0) === (assetId ?? void 0) && parseAmount(o.amount) >= requestedSats
|
|
1070
|
+
);
|
|
1071
|
+
if (!recipientOutput) {
|
|
890
1072
|
throw new Error(
|
|
891
|
-
`
|
|
1073
|
+
`Prepared transaction does not contain the requested output (to=${to}, amount=${amount}, asset=${assetId ?? "PMS"}). Refusing to sign a transaction that does not pay the intended recipient.`
|
|
892
1074
|
);
|
|
893
1075
|
}
|
|
894
|
-
const
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
if (change > 0n) {
|
|
905
|
-
outputs.push({ address: wallet.address, amount: formatAmount(change) });
|
|
1076
|
+
const localHash = txSigningMessage(
|
|
1077
|
+
this.config.networkId,
|
|
1078
|
+
unsigned_tx.inputs,
|
|
1079
|
+
unsigned_tx.outputs,
|
|
1080
|
+
unsigned_tx.fee
|
|
1081
|
+
);
|
|
1082
|
+
if (localHash !== tx_hash) {
|
|
1083
|
+
throw new Error(
|
|
1084
|
+
`tx_hash mismatch: server returned ${tx_hash}, locally computed ${localHash}. Either the client networkId ("${this.config.networkId}") does not match the node's network, or the server response was tampered with. Refusing to sign.`
|
|
1085
|
+
);
|
|
906
1086
|
}
|
|
907
|
-
const
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
index: utxo.outpoint.index
|
|
911
|
-
}
|
|
912
|
-
}));
|
|
913
|
-
const txCanonical = {
|
|
914
|
-
inputs,
|
|
915
|
-
outputs,
|
|
916
|
-
fee: formatAmount(fee)
|
|
917
|
-
};
|
|
918
|
-
const txMessage = JSON.stringify(txCanonical);
|
|
919
|
-
const txSignatureHex = wallet.sign(encodeUtf8(txMessage));
|
|
920
|
-
const txSigBytes = fromHex(txSignatureHex);
|
|
921
|
-
const txSigB64 = btoa(String.fromCharCode(...txSigBytes));
|
|
922
|
-
const unlocks = inputs.map(() => ({
|
|
1087
|
+
const sigHex = wallet.sign(encodeUtf8(tx_hash));
|
|
1088
|
+
const sigB64 = toBase64(fromHex(sigHex));
|
|
1089
|
+
const unlocks = unsigned_tx.inputs.map(() => ({
|
|
923
1090
|
pubkey_hex: wallet.publicKeyHex,
|
|
924
|
-
signature_b64:
|
|
1091
|
+
signature_b64: sigB64
|
|
925
1092
|
}));
|
|
926
1093
|
const tx = {
|
|
927
|
-
inputs,
|
|
928
|
-
outputs,
|
|
929
|
-
fee:
|
|
1094
|
+
inputs: unsigned_tx.inputs,
|
|
1095
|
+
outputs: unsigned_tx.outputs,
|
|
1096
|
+
fee: unsigned_tx.fee,
|
|
930
1097
|
unlocks
|
|
931
1098
|
};
|
|
932
|
-
const
|
|
933
|
-
const
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
signer_pk_hex: wallet.publicKeyHex
|
|
946
|
-
};
|
|
947
|
-
const messageToSign = JSON.stringify(canonicalView);
|
|
948
|
-
const signatureHex = wallet.sign(encodeUtf8(messageToSign));
|
|
949
|
-
const signatureBytes = fromHex(signatureHex);
|
|
950
|
-
const signatureB64 = btoa(String.fromCharCode(...signatureBytes));
|
|
951
|
-
const wireBlock = {
|
|
952
|
-
id: blockId,
|
|
953
|
-
parents,
|
|
954
|
-
payload_json: payloadJson,
|
|
955
|
-
nonce,
|
|
956
|
-
network_id: this.config.networkId,
|
|
957
|
-
protocol_version: this.config.protocolVersion,
|
|
958
|
-
signer_pk_hex: wallet.publicKeyHex,
|
|
959
|
-
signature_hex: signatureB64
|
|
960
|
-
};
|
|
961
|
-
return this.submitBlock(wireBlock);
|
|
1099
|
+
const recipientsXpk = [wallet.x25519PublicKeyHex];
|
|
1100
|
+
const toXpk = x25519FromAddress(to);
|
|
1101
|
+
if (toXpk && !recipientsXpk.includes(toXpk)) {
|
|
1102
|
+
recipientsXpk.push(toXpk);
|
|
1103
|
+
}
|
|
1104
|
+
const resp = await this.fetch(
|
|
1105
|
+
"/v1/wallet/tx/send",
|
|
1106
|
+
{
|
|
1107
|
+
method: "POST",
|
|
1108
|
+
body: JSON.stringify({ tx, recipients_xpk: recipientsXpk })
|
|
1109
|
+
}
|
|
1110
|
+
);
|
|
1111
|
+
return { ...resp, block_id: resp.id };
|
|
962
1112
|
}
|
|
963
1113
|
// ═══════════════════════════════════════════════════════════════════════
|
|
964
1114
|
// Méthodes NFT Cube (Burn et Mint spécialisé)
|
|
@@ -966,7 +1116,15 @@ var PmsClient = class {
|
|
|
966
1116
|
/**
|
|
967
1117
|
* Transférer un NFT à un autre propriétaire.
|
|
968
1118
|
* Prend en charge le re-chiffrement des métadonnées via le coordinateur.
|
|
969
|
-
*
|
|
1119
|
+
*
|
|
1120
|
+
* @deprecated Cette méthode soumet un WireBlock signé par la clé
|
|
1121
|
+
* utilisateur via `/submit/block`. Depuis dag-pms v0.9.0, l'engine tourne
|
|
1122
|
+
* en mode **single-writer** : tout bloc signé par une clé non-coordinateur
|
|
1123
|
+
* est rejeté. Cette méthode ne fonctionne que sur un réseau SANS
|
|
1124
|
+
* single-writer enforcement. Utilisez les flux server-side
|
|
1125
|
+
* (`/v1/nft/transfer/prepare` + endpoints serveur) qui forgent et signent
|
|
1126
|
+
* le bloc côté coordinateur.
|
|
1127
|
+
*
|
|
970
1128
|
* @param params - Paramètres du transfert
|
|
971
1129
|
* @param params.tokenId - Identifiant du NFT
|
|
972
1130
|
* @param params.to - Adresse du nouveau propriétaire
|
|
@@ -1002,7 +1160,7 @@ var PmsClient = class {
|
|
|
1002
1160
|
const payload = { Plain: { Nft: action } };
|
|
1003
1161
|
const payloadJson = JSON.stringify(payload);
|
|
1004
1162
|
const nonce = 0;
|
|
1005
|
-
const blockId = computeBlockId(parents,
|
|
1163
|
+
const blockId = computeBlockId(parents, payload, nonce);
|
|
1006
1164
|
const canonicalView = {
|
|
1007
1165
|
id: blockId,
|
|
1008
1166
|
parents,
|
|
@@ -1034,10 +1192,17 @@ var PmsClient = class {
|
|
|
1034
1192
|
* Seul le propriétaire du NFT peut le brûler.
|
|
1035
1193
|
* Une fois brûlé, le NFT est supprimé définitivement.
|
|
1036
1194
|
*
|
|
1037
|
-
* Pour les Cubes authentiques (avec signature Authority valide),
|
|
1195
|
+
* Pour les Cubes authentiques (avec signature Authority valide),
|
|
1038
1196
|
* un remboursement est calculé selon la formule:
|
|
1039
1197
|
* `(weight * size * density) / 10000` PMS
|
|
1040
|
-
*
|
|
1198
|
+
*
|
|
1199
|
+
* @deprecated Cette méthode poste un WireBlock signé par la clé
|
|
1200
|
+
* utilisateur. Depuis dag-pms v0.9.0, l'engine tourne en mode
|
|
1201
|
+
* **single-writer** : tout bloc signé par une clé non-coordinateur est
|
|
1202
|
+
* rejeté. Cette méthode ne fonctionne que sur un réseau SANS single-writer
|
|
1203
|
+
* enforcement. Le flux supporté est le burn server-side
|
|
1204
|
+
* (`/v1/nft/burn-simple`), où le serveur forge et signe le bloc.
|
|
1205
|
+
*
|
|
1041
1206
|
* @param params - Paramètres du burn
|
|
1042
1207
|
* @param params.tokenId - Identifiant du NFT à brûler
|
|
1043
1208
|
* @param params.wallet - Wallet PMS du propriétaire (doit être l'owner actuel)
|
|
@@ -1071,7 +1236,7 @@ var PmsClient = class {
|
|
|
1071
1236
|
};
|
|
1072
1237
|
const payloadJson = JSON.stringify(payload);
|
|
1073
1238
|
const nonce = 0;
|
|
1074
|
-
const blockId = computeBlockId(parents,
|
|
1239
|
+
const blockId = computeBlockId(parents, payload, nonce);
|
|
1075
1240
|
const canonicalView = {
|
|
1076
1241
|
id: blockId,
|
|
1077
1242
|
parents,
|
|
@@ -1103,7 +1268,14 @@ var PmsClient = class {
|
|
|
1103
1268
|
}
|
|
1104
1269
|
/**
|
|
1105
1270
|
* Brûle (détruit) plusieurs NFTs en une seule transaction.
|
|
1106
|
-
*
|
|
1271
|
+
*
|
|
1272
|
+
* @deprecated Cette méthode poste un WireBlock signé par la clé
|
|
1273
|
+
* utilisateur. Depuis dag-pms v0.9.0, l'engine tourne en mode
|
|
1274
|
+
* **single-writer** : tout bloc signé par une clé non-coordinateur est
|
|
1275
|
+
* rejeté. Cette méthode ne fonctionne que sur un réseau SANS single-writer
|
|
1276
|
+
* enforcement. Le flux supporté est le burn server-side
|
|
1277
|
+
* (`/v1/nft/burn-simple`), où le serveur forge et signe le bloc.
|
|
1278
|
+
*
|
|
1107
1279
|
* @param params - Paramètres du batch burn
|
|
1108
1280
|
* @param params.tokenIds - Liste des Identifiants des NFTs à brûler
|
|
1109
1281
|
* @param params.wallet - Wallet PMS du propriétaire
|
|
@@ -1128,7 +1300,7 @@ var PmsClient = class {
|
|
|
1128
1300
|
};
|
|
1129
1301
|
const payloadJson = JSON.stringify(payload);
|
|
1130
1302
|
const nonce = 0;
|
|
1131
|
-
const blockId = computeBlockId(parents,
|
|
1303
|
+
const blockId = computeBlockId(parents, payload, nonce);
|
|
1132
1304
|
const canonicalView = {
|
|
1133
1305
|
id: blockId,
|
|
1134
1306
|
parents,
|
|
@@ -1396,12 +1568,19 @@ function mergeAbortSignals(a, b) {
|
|
|
1396
1568
|
return controller.signal;
|
|
1397
1569
|
}
|
|
1398
1570
|
export {
|
|
1571
|
+
DAY_MS,
|
|
1399
1572
|
PmsClient,
|
|
1400
1573
|
PmsWallet,
|
|
1401
1574
|
decryptPayload,
|
|
1575
|
+
effectiveValue,
|
|
1402
1576
|
formatAmount,
|
|
1403
1577
|
fromHex,
|
|
1578
|
+
hashlockHash,
|
|
1404
1579
|
isValidMnemonic,
|
|
1580
|
+
makeUnlock,
|
|
1581
|
+
multisigAddress,
|
|
1405
1582
|
parseAmount,
|
|
1406
|
-
|
|
1583
|
+
spendableUtxos,
|
|
1584
|
+
toHex,
|
|
1585
|
+
txSigningMessage
|
|
1407
1586
|
};
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empereur-rouge/pms-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "TypeScript SDK for PMS (Planetary Monetary System) — wallet management, transactions, NFTs, and DAG interactions",
|
|
5
5
|
"author": "empereur-rouge",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"main": "dist/index.
|
|
8
|
-
"module": "dist/index.
|
|
7
|
+
"main": "dist/index.cjs",
|
|
8
|
+
"module": "dist/index.js",
|
|
9
9
|
"types": "dist/index.d.ts",
|
|
10
10
|
"type": "module",
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
13
|
"types": "./dist/index.d.ts",
|
|
14
|
-
"import": "./dist/index.
|
|
15
|
-
"require": "./dist/index.
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.cjs"
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"files": [
|