@palliora.org/chainsdk 0.3.3 → 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/AGENTS.md +61 -0
- package/CHAIN-RULES.md +760 -0
- package/README.md +161 -26
- package/dist/index.cjs +1422 -136
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1369 -24
- package/dist/index.d.ts +1369 -24
- package/dist/index.js +1391 -105
- package/dist/index.js.map +1 -1
- package/package.json +20 -11
package/dist/index.js
CHANGED
|
@@ -71,6 +71,9 @@ async function createAccount(input, type, name = "default", cryptoType = "sr2551
|
|
|
71
71
|
throw new Error("Invalid input type");
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
+
async function createAccountFromMagicLink(signature, name = "default", cryptoType = "sr25519" /* SR25519 */) {
|
|
75
|
+
return createAccount(signature, "derived" /* DERIVED */, name, cryptoType);
|
|
76
|
+
}
|
|
74
77
|
function pairFromPrivateKeyHex(privateKeyHex, cryptoType) {
|
|
75
78
|
const privateKey = hexToU8a(privateKeyHex);
|
|
76
79
|
switch (cryptoType) {
|
|
@@ -201,6 +204,13 @@ var API_TYPES = {
|
|
|
201
204
|
active: "u32",
|
|
202
205
|
maximum: "u32"
|
|
203
206
|
},
|
|
207
|
+
CurrencyId: {
|
|
208
|
+
_enum: {
|
|
209
|
+
Native: "Null",
|
|
210
|
+
USDC: "Null",
|
|
211
|
+
ForeignAsset: "u32"
|
|
212
|
+
}
|
|
213
|
+
},
|
|
204
214
|
GuardianNwParams: {
|
|
205
215
|
kzg: "Vec<u8>",
|
|
206
216
|
aggKey: "Vec<u8>"
|
|
@@ -372,9 +382,15 @@ var API_TYPES = {
|
|
|
372
382
|
StoreType: {
|
|
373
383
|
_enum: {
|
|
374
384
|
Dataset: "Null",
|
|
385
|
+
// 0
|
|
375
386
|
Model: "Null",
|
|
387
|
+
// 1
|
|
376
388
|
Agent: "Null",
|
|
389
|
+
// 2
|
|
390
|
+
Executable: "Null",
|
|
391
|
+
// 3
|
|
377
392
|
Other: "Null"
|
|
393
|
+
// 4
|
|
378
394
|
}
|
|
379
395
|
},
|
|
380
396
|
ComputeMetadata: {
|
|
@@ -402,7 +418,8 @@ var API_TYPES = {
|
|
|
402
418
|
preCheck: "Option<ComputeInfo>",
|
|
403
419
|
compute: "ComputeInfo",
|
|
404
420
|
postCheck: "Option<ComputeInfo>",
|
|
405
|
-
resultCipher: "CipherSuite"
|
|
421
|
+
resultCipher: "CipherSuite",
|
|
422
|
+
currencyId: "CurrencyId"
|
|
406
423
|
},
|
|
407
424
|
AgreementInfo: {
|
|
408
425
|
status: "AgreementStatus",
|
|
@@ -422,13 +439,16 @@ var API_TYPES = {
|
|
|
422
439
|
fhe: "bool",
|
|
423
440
|
zkp: "bool"
|
|
424
441
|
},
|
|
442
|
+
ComputeType: {
|
|
443
|
+
_enum: ["Trusted", "Tee", "Mpc", "Fhe", "Zkp"]
|
|
444
|
+
},
|
|
425
445
|
GuardianPrefs: {
|
|
426
446
|
pubKey: "[u8; 32]",
|
|
427
447
|
guardian: "bool",
|
|
428
448
|
verifier: "bool",
|
|
429
449
|
compute: "bool",
|
|
430
450
|
computePrefs: "Option<ComputePrefs>",
|
|
431
|
-
|
|
451
|
+
feeThresholds: "Vec<(ComputeType, u128)>"
|
|
432
452
|
},
|
|
433
453
|
BlockLengthColumns: "Compact<u32>",
|
|
434
454
|
BlockLengthRows: "Compact<u32>",
|
|
@@ -538,6 +558,18 @@ var API_EXTENSIONS = {
|
|
|
538
558
|
compute: "ComputePayload"
|
|
539
559
|
},
|
|
540
560
|
payload: {}
|
|
561
|
+
},
|
|
562
|
+
// Replaces pallet_transaction_payment::ChargeTransactionPayment. Since this
|
|
563
|
+
// identifier isn't one @polkadot/api knows natively, this definition entirely
|
|
564
|
+
// replaces (not merges with) the built-in one, so `tip` must be re-declared
|
|
565
|
+
// here alongside the new `currencyId` field or it silently drops from the
|
|
566
|
+
// encoded extra bytes, shifting every extrinsic out of alignment.
|
|
567
|
+
ChargeCurrencyTransactionPayment: {
|
|
568
|
+
extrinsic: {
|
|
569
|
+
tip: "Compact<Balance>",
|
|
570
|
+
currencyId: "Option<CurrencyId>"
|
|
571
|
+
},
|
|
572
|
+
payload: {}
|
|
541
573
|
}
|
|
542
574
|
};
|
|
543
575
|
|
|
@@ -827,18 +859,49 @@ function assert(condition, message) {
|
|
|
827
859
|
|
|
828
860
|
// src/config.ts
|
|
829
861
|
import { WsProvider } from "@polkadot/api";
|
|
830
|
-
var
|
|
831
|
-
var
|
|
832
|
-
var
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
function
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
862
|
+
var config = null;
|
|
863
|
+
var cachedProvider = null;
|
|
864
|
+
var cachedProviderUrl = null;
|
|
865
|
+
function init(options) {
|
|
866
|
+
config = { ...config, ...options };
|
|
867
|
+
}
|
|
868
|
+
function isInitialized() {
|
|
869
|
+
return config !== null;
|
|
870
|
+
}
|
|
871
|
+
function resetConfig() {
|
|
872
|
+
config = null;
|
|
873
|
+
cachedProvider = null;
|
|
874
|
+
cachedProviderUrl = null;
|
|
875
|
+
}
|
|
876
|
+
function read(key) {
|
|
877
|
+
if (!config) {
|
|
878
|
+
throw new Error(
|
|
879
|
+
`Palliora SDK is not initialized: cannot read "${key}". Call init({ ${key}: ... }) before using the SDK.`
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
const value = config[key];
|
|
883
|
+
if (value === void 0) {
|
|
884
|
+
throw new Error(
|
|
885
|
+
`Palliora SDK config "${key}" is not set. Pass it to init({ ${key}: ... }).`
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
return value;
|
|
889
|
+
}
|
|
890
|
+
var getPallioraWs = () => read("pallioraWs");
|
|
891
|
+
var getPallioraRpcUrl = () => read("pallioraRpcUrl");
|
|
892
|
+
var getCostEstimatorUrl = () => read("costEstimatorUrl");
|
|
893
|
+
var getAuthServiceUrl = () => read("authServiceUrl");
|
|
894
|
+
var getAwsRegion = () => read("awsRegion");
|
|
895
|
+
var getAwsS3Bucket = () => read("awsS3Bucket");
|
|
896
|
+
var isDebug = () => config?.debug ?? false;
|
|
897
|
+
var waitsForFinalization = () => config?.txWaitFinalization ?? false;
|
|
898
|
+
function getProvider() {
|
|
899
|
+
const url = getPallioraWs();
|
|
900
|
+
if (!cachedProvider || cachedProviderUrl !== url) {
|
|
901
|
+
cachedProvider = new WsProvider(url, 1e4);
|
|
902
|
+
cachedProviderUrl = url;
|
|
903
|
+
}
|
|
904
|
+
return cachedProvider;
|
|
842
905
|
}
|
|
843
906
|
|
|
844
907
|
// src/utils/helper.ts
|
|
@@ -886,7 +949,7 @@ var decodeField = (field, expectedLength) => {
|
|
|
886
949
|
return bytes;
|
|
887
950
|
};
|
|
888
951
|
var debugLog = (message, ...optionalParams) => {
|
|
889
|
-
if (
|
|
952
|
+
if (isDebug()) {
|
|
890
953
|
console.log(message, ...optionalParams);
|
|
891
954
|
}
|
|
892
955
|
};
|
|
@@ -948,8 +1011,8 @@ var encKeyring = null;
|
|
|
948
1011
|
var apiListenersAttached = false;
|
|
949
1012
|
var apiTeardownInProgress = false;
|
|
950
1013
|
async function getApi(cb) {
|
|
951
|
-
|
|
952
|
-
if (api &&
|
|
1014
|
+
const pallioraWs = getPallioraWs();
|
|
1015
|
+
if (api && pallioraWs !== apiUrl) {
|
|
953
1016
|
const staleApi = api;
|
|
954
1017
|
api = null;
|
|
955
1018
|
apiUrl = null;
|
|
@@ -960,12 +1023,12 @@ async function getApi(cb) {
|
|
|
960
1023
|
}
|
|
961
1024
|
if (!api) {
|
|
962
1025
|
api = await ApiPromise.create({
|
|
963
|
-
provider,
|
|
1026
|
+
provider: getProvider(),
|
|
964
1027
|
rpc: API_RPC,
|
|
965
1028
|
types: API_TYPES,
|
|
966
1029
|
signedExtensions: API_EXTENSIONS
|
|
967
1030
|
});
|
|
968
|
-
apiUrl =
|
|
1031
|
+
apiUrl = pallioraWs;
|
|
969
1032
|
}
|
|
970
1033
|
const isNode = typeof process !== "undefined" && typeof process.exit === "function";
|
|
971
1034
|
const isTest = typeof process !== "undefined" && process.env?.NODE_ENV === "test";
|
|
@@ -991,6 +1054,16 @@ async function getApi(cb) {
|
|
|
991
1054
|
}
|
|
992
1055
|
return api;
|
|
993
1056
|
}
|
|
1057
|
+
async function disconnectApi() {
|
|
1058
|
+
if (!api) return;
|
|
1059
|
+
const current = api;
|
|
1060
|
+
api = null;
|
|
1061
|
+
apiUrl = null;
|
|
1062
|
+
apiListenersAttached = false;
|
|
1063
|
+
apiTeardownInProgress = false;
|
|
1064
|
+
await current.disconnect().catch(() => {
|
|
1065
|
+
});
|
|
1066
|
+
}
|
|
994
1067
|
async function getKeyring() {
|
|
995
1068
|
if (!keyring) {
|
|
996
1069
|
await waitReady2();
|
|
@@ -1013,6 +1086,7 @@ import { isFunction as isFunction2 } from "@polkadot/util";
|
|
|
1013
1086
|
import bs58 from "bs58";
|
|
1014
1087
|
|
|
1015
1088
|
// src/guardian/active.ts
|
|
1089
|
+
import { waitReady as waitReady3 } from "@polkadot/wasm-crypto";
|
|
1016
1090
|
import { isFunction } from "@polkadot/util";
|
|
1017
1091
|
var getGuardianList = async () => {
|
|
1018
1092
|
const api2 = await getApi();
|
|
@@ -1027,6 +1101,26 @@ var getGuardianList = async () => {
|
|
|
1027
1101
|
const list = (await rpc[section]["guardianList"]()).map((item) => [item.toString()]).flat(1);
|
|
1028
1102
|
return list;
|
|
1029
1103
|
};
|
|
1104
|
+
async function getActiveGuardians(apiInstance) {
|
|
1105
|
+
await waitReady3();
|
|
1106
|
+
const api2 = apiInstance ?? await getApi();
|
|
1107
|
+
if (!api2) throw new Error("API not initialized");
|
|
1108
|
+
const guardians = await api2.query.guardian.guardians();
|
|
1109
|
+
const accounts = guardians?.toJSON() || [];
|
|
1110
|
+
return Promise.all(
|
|
1111
|
+
accounts.map(async (account) => {
|
|
1112
|
+
const [prefs, ledger] = await Promise.all([
|
|
1113
|
+
api2.query.staking.guardians(account),
|
|
1114
|
+
api2.query.staking.ledger(account)
|
|
1115
|
+
]);
|
|
1116
|
+
return {
|
|
1117
|
+
account,
|
|
1118
|
+
guardianPrefs: prefs?.toHuman?.() ?? null,
|
|
1119
|
+
stakersOverview: ledger?.toHuman?.() ?? null
|
|
1120
|
+
};
|
|
1121
|
+
})
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1030
1124
|
|
|
1031
1125
|
// src/guardian/group.ts
|
|
1032
1126
|
var createGuardianGroup = async (account, selectedGuardians) => {
|
|
@@ -1087,32 +1181,125 @@ var createGuardianGroupAndWatch = async (account, guardians, maxBlocks = 20) =>
|
|
|
1087
1181
|
guardians
|
|
1088
1182
|
};
|
|
1089
1183
|
};
|
|
1184
|
+
async function findGuardianGroupInfoExtrinsic(api2, startBlock, maxBlocks) {
|
|
1185
|
+
const tip = (await api2.rpc.chain.getHeader()).number.toNumber();
|
|
1186
|
+
const endBlock = maxBlocks > 0 ? Math.min(startBlock + maxBlocks - 1, tip) : tip;
|
|
1187
|
+
for (let blockNumber = startBlock; blockNumber <= endBlock; blockNumber++) {
|
|
1188
|
+
const blockHash = await api2.rpc.chain.getBlockHash(blockNumber);
|
|
1189
|
+
const signedBlock = await api2.rpc.chain.getBlock(blockHash);
|
|
1190
|
+
const extrinsics = signedBlock.block.extrinsics;
|
|
1191
|
+
for (let index = 0; index < extrinsics.length; index++) {
|
|
1192
|
+
const ext = extrinsics[index];
|
|
1193
|
+
if (ext?.method?.section?.toLowerCase() === "dataavailability" && ext?.method?.method?.toLowerCase() === "daccguardiangroupinfo") {
|
|
1194
|
+
return { blockNumber, index };
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
throw new Error(
|
|
1199
|
+
`No daccGuardianGroupInfo extrinsic found in blocks ${startBlock}-${endBlock} (searched ${Math.max(endBlock - startBlock + 1, 0)} block(s) after the creation extrinsic)`
|
|
1200
|
+
);
|
|
1201
|
+
}
|
|
1202
|
+
var getGuardianGroupInfo = async (creationRef, resultRef, maxBlocks = 20) => {
|
|
1203
|
+
assert(creationRef, "Group creation extrinsic reference is required");
|
|
1204
|
+
const api2 = await getApi();
|
|
1205
|
+
assert(api2, "Failed to initialize API");
|
|
1206
|
+
debugLog(`Reading guardian group creation extrinsic at block ${creationRef.blockNumber}, index ${creationRef.index}...`);
|
|
1207
|
+
const { raw: creationExt } = await fetchAndDecodeExtrinsic(creationRef.blockNumber, creationRef.index);
|
|
1208
|
+
assert(
|
|
1209
|
+
creationExt?.method?.section?.toLowerCase() === "dataavailability" && creationExt?.method?.method?.toLowerCase() === "daccguardiangroup",
|
|
1210
|
+
`Extrinsic at block ${creationRef.blockNumber}, index ${creationRef.index} is not a daccGuardianGroup call (found ${creationExt?.method?.section}.${creationExt?.method?.method})`
|
|
1211
|
+
);
|
|
1212
|
+
const [selectedGuardiansArg] = creationExt.method.args;
|
|
1213
|
+
const guardians = Array.from(selectedGuardiansArg).map((g) => g.toString());
|
|
1214
|
+
debugLog(`Guardian group creation extrinsic decoded: guardians=${guardians.join(", ")}`);
|
|
1215
|
+
const resolvedResultRef = resultRef ?? await (async () => {
|
|
1216
|
+
debugLog(
|
|
1217
|
+
`No result extrinsic reference given, scanning forward from block ${creationRef.blockNumber + 1} for daccGuardianGroupInfo...`
|
|
1218
|
+
);
|
|
1219
|
+
return findGuardianGroupInfoExtrinsic(api2, creationRef.blockNumber + 1, maxBlocks);
|
|
1220
|
+
})();
|
|
1221
|
+
debugLog(`Reading guardian group result extrinsic at block ${resolvedResultRef.blockNumber}, index ${resolvedResultRef.index}...`);
|
|
1222
|
+
const { raw: resultExt } = await fetchAndDecodeExtrinsic(resolvedResultRef.blockNumber, resolvedResultRef.index);
|
|
1223
|
+
assert(
|
|
1224
|
+
resultExt?.method?.section?.toLowerCase() === "dataavailability" && resultExt?.method?.method?.toLowerCase() === "daccguardiangroupinfo",
|
|
1225
|
+
`Extrinsic at block ${resolvedResultRef.blockNumber}, index ${resolvedResultRef.index} is not a daccGuardianGroupInfo call (found ${resultExt?.method?.section}.${resultExt?.method?.method})`
|
|
1226
|
+
);
|
|
1227
|
+
const [group_id, group_pk, tau_params, agg_key] = resultExt.method.args;
|
|
1228
|
+
debugLog(`Guardian group result extrinsic decoded: group_id=${group_id.toHex()}`);
|
|
1229
|
+
return {
|
|
1230
|
+
groupId: group_id.toHex(),
|
|
1231
|
+
groupPk: group_pk.toHex(),
|
|
1232
|
+
tauParams: tau_params.toHex(),
|
|
1233
|
+
aggKey: agg_key.toHex(),
|
|
1234
|
+
guardians
|
|
1235
|
+
};
|
|
1236
|
+
};
|
|
1090
1237
|
|
|
1091
1238
|
// src/guardian/join.ts
|
|
1239
|
+
var COMPUTE_TYPES = ["trusted", "tee", "mpc", "fhe", "zkp"];
|
|
1240
|
+
var CHAIN_COMPUTE_TYPE = {
|
|
1241
|
+
trusted: "Trusted",
|
|
1242
|
+
tee: "Tee",
|
|
1243
|
+
mpc: "Mpc",
|
|
1244
|
+
fhe: "Fhe",
|
|
1245
|
+
zkp: "Zkp"
|
|
1246
|
+
};
|
|
1247
|
+
function parseComputeTypes(compute) {
|
|
1248
|
+
const requested = (compute || "").split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
1249
|
+
return COMPUTE_TYPES.filter((type) => requested.includes(type));
|
|
1250
|
+
}
|
|
1251
|
+
function buildFeeThresholds(fee, computeTypes) {
|
|
1252
|
+
if (fee === void 0 || fee === null || fee === "") {
|
|
1253
|
+
return [];
|
|
1254
|
+
}
|
|
1255
|
+
if (typeof fee !== "object") {
|
|
1256
|
+
assert(
|
|
1257
|
+
computeTypes.length > 0,
|
|
1258
|
+
"A single fee threshold needs compute preferences to apply to. Set compute preferences, or declare thresholds per compute type."
|
|
1259
|
+
);
|
|
1260
|
+
return computeTypes.map((type) => [CHAIN_COMPUTE_TYPE[type], BigInt(fee)]);
|
|
1261
|
+
}
|
|
1262
|
+
return Object.entries(fee).map(([type, amount]) => {
|
|
1263
|
+
assert(
|
|
1264
|
+
COMPUTE_TYPES.includes(type),
|
|
1265
|
+
`Unknown compute type "${type}" in fee thresholds. Allowed: ${COMPUTE_TYPES.join(", ")}`
|
|
1266
|
+
);
|
|
1267
|
+
assert(
|
|
1268
|
+
computeTypes.includes(type),
|
|
1269
|
+
`Fee threshold declared for "${type}", which is not among the compute preferences (${computeTypes.join(", ") || "none"})`
|
|
1270
|
+
);
|
|
1271
|
+
return [CHAIN_COMPUTE_TYPE[type], BigInt(amount)];
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1092
1274
|
async function joinGuardian(account, prefs) {
|
|
1093
1275
|
const api2 = await getApi();
|
|
1094
1276
|
assert(api2, "API not initialized");
|
|
1095
1277
|
assert(account, "Account not initialized");
|
|
1096
|
-
const
|
|
1097
|
-
const
|
|
1278
|
+
const computeTypes = parseComputeTypes(prefs.compute);
|
|
1279
|
+
const feeThresholds = buildFeeThresholds(prefs.fee, computeTypes);
|
|
1098
1280
|
const guardianPrefs = {
|
|
1099
1281
|
pubKey: account.publicKey,
|
|
1100
1282
|
guardian: prefs.standard,
|
|
1101
1283
|
verifier: prefs.verifier,
|
|
1102
1284
|
compute: prefs.compute ? true : false,
|
|
1103
1285
|
computePrefs: {
|
|
1104
|
-
trusted:
|
|
1105
|
-
tee:
|
|
1106
|
-
mpc:
|
|
1107
|
-
fhe:
|
|
1108
|
-
zkp:
|
|
1286
|
+
trusted: computeTypes.includes("trusted"),
|
|
1287
|
+
tee: computeTypes.includes("tee"),
|
|
1288
|
+
mpc: computeTypes.includes("mpc"),
|
|
1289
|
+
fhe: computeTypes.includes("fhe"),
|
|
1290
|
+
zkp: computeTypes.includes("zkp")
|
|
1109
1291
|
},
|
|
1110
|
-
|
|
1292
|
+
feeThresholds
|
|
1111
1293
|
};
|
|
1112
1294
|
debugLog(
|
|
1113
1295
|
account.address,
|
|
1114
1296
|
"joining as guardian with preferences:",
|
|
1115
|
-
{
|
|
1297
|
+
{
|
|
1298
|
+
...guardianPrefs,
|
|
1299
|
+
feeThresholds: feeThresholds.map(
|
|
1300
|
+
([type, threshold]) => `${type}: ${formatPaliAmount(threshold)}`
|
|
1301
|
+
)
|
|
1302
|
+
}
|
|
1116
1303
|
);
|
|
1117
1304
|
const guardTx = api2.tx.staking.guard(guardianPrefs);
|
|
1118
1305
|
const hash = await signAndSend(guardTx, account);
|
|
@@ -1120,13 +1307,14 @@ async function joinGuardian(account, prefs) {
|
|
|
1120
1307
|
}
|
|
1121
1308
|
|
|
1122
1309
|
// src/chain/utils.ts
|
|
1123
|
-
var signAndSend = async (
|
|
1310
|
+
var signAndSend = async (request2, account, opts = DEFAULT_COMPUTE_PAYLOAD) => {
|
|
1311
|
+
const signOpts = { currencyId: null, ...opts };
|
|
1124
1312
|
const tx_result = await new Promise((res, err) => {
|
|
1125
|
-
|
|
1313
|
+
request2.signAndSend(account, signOpts, (result) => {
|
|
1126
1314
|
if (result.isFinalized) {
|
|
1127
1315
|
res(result);
|
|
1128
1316
|
}
|
|
1129
|
-
if (!
|
|
1317
|
+
if (!waitsForFinalization() && result.isInBlock) {
|
|
1130
1318
|
res(result);
|
|
1131
1319
|
}
|
|
1132
1320
|
if (result.isError) err(result);
|
|
@@ -1150,6 +1338,21 @@ var signAndSend = async (request, account, opts = DEFAULT_COMPUTE_PAYLOAD) => {
|
|
|
1150
1338
|
tx_result
|
|
1151
1339
|
};
|
|
1152
1340
|
};
|
|
1341
|
+
var retrySignAndSend = async (request2, account, opts, retries = 3, backoffMs = 1e3) => {
|
|
1342
|
+
let lastError;
|
|
1343
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
1344
|
+
try {
|
|
1345
|
+
return await signAndSend(request2, account, opts);
|
|
1346
|
+
} catch (err) {
|
|
1347
|
+
lastError = err;
|
|
1348
|
+
if (attempt === retries) break;
|
|
1349
|
+
const delay = backoffMs * 2 ** attempt;
|
|
1350
|
+
debugLog(`retrySignAndSend: attempt ${attempt + 1} failed, retrying in ${delay}ms`, err);
|
|
1351
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
throw lastError;
|
|
1355
|
+
};
|
|
1153
1356
|
var getFileMetadataCall = async (api2, metadataRef) => {
|
|
1154
1357
|
const block = await getBlock(api2, metadataRef[0]);
|
|
1155
1358
|
const call = block.block.extrinsics[metadataRef[1]];
|
|
@@ -1197,6 +1400,26 @@ var getGuardianNwParams = async () => {
|
|
|
1197
1400
|
throw error;
|
|
1198
1401
|
}
|
|
1199
1402
|
};
|
|
1403
|
+
async function getContractInfo(contractId) {
|
|
1404
|
+
const api2 = await getApi();
|
|
1405
|
+
if (!api2) throw new Error("API not initialized");
|
|
1406
|
+
assert(
|
|
1407
|
+
isFunction2(api2.query["compute"]?.["contracts"]),
|
|
1408
|
+
`api.query.compute.contracts does not exist`
|
|
1409
|
+
);
|
|
1410
|
+
const raw = await api2.query["compute"]["contracts"](contractId);
|
|
1411
|
+
const info = raw.toPrimitive();
|
|
1412
|
+
if (!info) return null;
|
|
1413
|
+
return {
|
|
1414
|
+
status: info.status,
|
|
1415
|
+
owner: info.owner,
|
|
1416
|
+
originBlock: info.originBlock,
|
|
1417
|
+
invocationBlock: info.invocationBlock,
|
|
1418
|
+
index: info.index,
|
|
1419
|
+
usagePrice: BigInt(info.usagePrice),
|
|
1420
|
+
contractType: info.contractType
|
|
1421
|
+
};
|
|
1422
|
+
}
|
|
1200
1423
|
async function fetchAndDecodeExtrinsic(blockHeight, extrinsicIndex) {
|
|
1201
1424
|
const api2 = await getApi();
|
|
1202
1425
|
if (!api2) throw new Error("API not initialized");
|
|
@@ -1212,6 +1435,11 @@ async function fetchAndDecodeExtrinsic(blockHeight, extrinsicIndex) {
|
|
|
1212
1435
|
const decoded = raw.toHuman();
|
|
1213
1436
|
return { raw, decoded };
|
|
1214
1437
|
}
|
|
1438
|
+
function findEvent(events, section, method) {
|
|
1439
|
+
return events.find(
|
|
1440
|
+
(record) => record.event.section.toLowerCase() === section.toLowerCase() && record.event.method.toLowerCase() === method.toLowerCase()
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1215
1443
|
var scanForBlockEvent = (api2, filter, startBlock, maxBlocks = 20) => {
|
|
1216
1444
|
const hasPredicate = "predicate" in filter;
|
|
1217
1445
|
let blocksScanned = 0;
|
|
@@ -1256,6 +1484,28 @@ var scanForBlockEvent = (api2, filter, startBlock, maxBlocks = 20) => {
|
|
|
1256
1484
|
);
|
|
1257
1485
|
});
|
|
1258
1486
|
};
|
|
1487
|
+
async function waitForNextBlock() {
|
|
1488
|
+
const api2 = await getApi();
|
|
1489
|
+
if (!api2) throw new Error("API not initialized");
|
|
1490
|
+
return new Promise((resolve, reject) => {
|
|
1491
|
+
let unsubFn;
|
|
1492
|
+
let settled = false;
|
|
1493
|
+
api2.rpc.chain.subscribeNewHeads((header) => {
|
|
1494
|
+
if (settled) return;
|
|
1495
|
+
settled = true;
|
|
1496
|
+
unsubFn?.();
|
|
1497
|
+
resolve({ blockNumber: header.number.toNumber(), blockHash: header.hash.toHex() });
|
|
1498
|
+
}).then((fn) => {
|
|
1499
|
+
if (settled) fn();
|
|
1500
|
+
else unsubFn = fn;
|
|
1501
|
+
}).catch((err) => {
|
|
1502
|
+
if (!settled) {
|
|
1503
|
+
settled = true;
|
|
1504
|
+
reject(err);
|
|
1505
|
+
}
|
|
1506
|
+
});
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1259
1509
|
async function watchForSubmissionReceipt(requestId, timeoutMs = 10 * 60 * 1e3) {
|
|
1260
1510
|
const api2 = await getApi();
|
|
1261
1511
|
if (!api2) throw new Error("API not initialized");
|
|
@@ -1321,22 +1571,18 @@ async function getAgreementCreatedRequestId(blockHeight, extrinsicIndex) {
|
|
|
1321
1571
|
const blockHash = await api2.rpc.chain.getBlockHash(blockHeight);
|
|
1322
1572
|
const apiAt = await api2.at(blockHash);
|
|
1323
1573
|
const allEvents = await apiAt.query.system.events();
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
} else if (dataHuman !== null && typeof dataHuman === "object") {
|
|
1337
|
-
const id = dataHuman["requestId"] ?? dataHuman["request_id"] ?? dataHuman["id"];
|
|
1338
|
-
if (id != null) return String(id);
|
|
1339
|
-
}
|
|
1574
|
+
const extrinsicEvents = allEvents.filter(
|
|
1575
|
+
(record) => record.phase.isApplyExtrinsic && record.phase.asApplyExtrinsic.toNumber() === extrinsicIndex
|
|
1576
|
+
);
|
|
1577
|
+
const match = findEvent(extrinsicEvents, "compute", "AgreementCreated");
|
|
1578
|
+
if (!match) return null;
|
|
1579
|
+
const dataHuman = match.event.data.toHuman();
|
|
1580
|
+
if (Array.isArray(dataHuman)) {
|
|
1581
|
+
const first = dataHuman[0];
|
|
1582
|
+
if (first != null) return String(first);
|
|
1583
|
+
} else if (dataHuman !== null && typeof dataHuman === "object") {
|
|
1584
|
+
const id = dataHuman["requestId"] ?? dataHuman["request_id"] ?? dataHuman["id"];
|
|
1585
|
+
if (id != null) return String(id);
|
|
1340
1586
|
}
|
|
1341
1587
|
return null;
|
|
1342
1588
|
}
|
|
@@ -1437,12 +1683,12 @@ var MCryptFsWriter = class {
|
|
|
1437
1683
|
return new Blob([blockNumberBuffer, extIndexBuffer, chunk]);
|
|
1438
1684
|
}
|
|
1439
1685
|
async writeChunk(chunk) {
|
|
1440
|
-
const
|
|
1686
|
+
const request2 = this._api.tx.dataAvailability.submitData(
|
|
1441
1687
|
Array.from(new Uint8Array(await chunk.arrayBuffer()))
|
|
1442
1688
|
);
|
|
1443
1689
|
console.log("account: ", this._account);
|
|
1444
1690
|
return new Promise((resolve) => {
|
|
1445
|
-
|
|
1691
|
+
request2.signAndSend(this._account, { app_id: 1, currencyId: null }, (result) => {
|
|
1446
1692
|
if (result.isInBlock || result.isFinalized || result.isError) {
|
|
1447
1693
|
resolve({
|
|
1448
1694
|
blockNumber: result.blockNumber?.toNumber() ?? 0,
|
|
@@ -1472,15 +1718,15 @@ var MCryptFsWriter = class {
|
|
|
1472
1718
|
chosen_guardians: this._guardianInfo.guardians,
|
|
1473
1719
|
blobRef: [blobRef.blockNumber, blobRef.extrinsicIndex]
|
|
1474
1720
|
});
|
|
1475
|
-
const
|
|
1476
|
-
return await signAndSend(
|
|
1721
|
+
const request2 = this._api.tx.dataAvailability.submitData(modelSubmit);
|
|
1722
|
+
return await signAndSend(request2, account);
|
|
1477
1723
|
}
|
|
1478
1724
|
async writeMetadata() {
|
|
1479
1725
|
const encoder = new TextEncoder();
|
|
1480
1726
|
const fileName = this._fileName;
|
|
1481
1727
|
const datasetRef = await this.submitKey(this._account, this._fileKey);
|
|
1482
1728
|
const keyRef = [datasetRef.blockNumber, datasetRef.index];
|
|
1483
|
-
const
|
|
1729
|
+
const request2 = this._api.tx.dataAvailability.daccRegisterData(
|
|
1484
1730
|
Array.from(new TextEncoder().encode(fileName)),
|
|
1485
1731
|
Array.from(new TextEncoder().encode(this._description)),
|
|
1486
1732
|
keyRef,
|
|
@@ -1489,7 +1735,7 @@ var MCryptFsWriter = class {
|
|
|
1489
1735
|
Array.from(encoder.encode(this._ownerL2Address)),
|
|
1490
1736
|
this._guardianInfo.groupId
|
|
1491
1737
|
);
|
|
1492
|
-
return await signAndSend(
|
|
1738
|
+
return await signAndSend(request2, this._account);
|
|
1493
1739
|
}
|
|
1494
1740
|
async writeFile() {
|
|
1495
1741
|
const chunks = [];
|
|
@@ -1556,6 +1802,90 @@ var FileFromMetadataRef = async (mcryptApi, metadataRef) => {
|
|
|
1556
1802
|
return new MCryptFs(mcryptApi, metadataRef, metadata);
|
|
1557
1803
|
};
|
|
1558
1804
|
|
|
1805
|
+
// src/chain/blocks.ts
|
|
1806
|
+
import { waitReady as waitReady4 } from "@polkadot/wasm-crypto";
|
|
1807
|
+
async function getLatestBlocks(count, page = 0, apiInstance) {
|
|
1808
|
+
await waitReady4();
|
|
1809
|
+
const api2 = apiInstance ?? await getApi();
|
|
1810
|
+
if (!api2) throw new Error("API not initialized");
|
|
1811
|
+
const header = await api2.rpc.chain.getHeader();
|
|
1812
|
+
const latestHeight = header.number.toNumber();
|
|
1813
|
+
const start = latestHeight - page * count;
|
|
1814
|
+
if (start < 0) {
|
|
1815
|
+
return { blocks: [], latestHeight };
|
|
1816
|
+
}
|
|
1817
|
+
const heights = [];
|
|
1818
|
+
for (let height = start; height >= Math.max(0, start - count + 1); height -= 1) {
|
|
1819
|
+
heights.push(height);
|
|
1820
|
+
}
|
|
1821
|
+
const blocks = await Promise.all(
|
|
1822
|
+
heights.map(async (height) => {
|
|
1823
|
+
const hash = await api2.rpc.chain.getBlockHash(height);
|
|
1824
|
+
const [signed, derived, at] = await Promise.all([
|
|
1825
|
+
api2.rpc.chain.getBlock(hash),
|
|
1826
|
+
api2.derive.chain.getHeader(hash).catch(() => null),
|
|
1827
|
+
api2.at(hash)
|
|
1828
|
+
]);
|
|
1829
|
+
const [timestamp, events] = await Promise.all([
|
|
1830
|
+
at.query.timestamp.now(),
|
|
1831
|
+
at.query.system.events()
|
|
1832
|
+
]);
|
|
1833
|
+
return {
|
|
1834
|
+
height,
|
|
1835
|
+
hash: hash.toHex(),
|
|
1836
|
+
time: Number(timestamp.toString()),
|
|
1837
|
+
validator: derived?.author?.toString?.() ?? "",
|
|
1838
|
+
extrinsicsCount: signed.block.extrinsics.length,
|
|
1839
|
+
eventsCount: events.length
|
|
1840
|
+
};
|
|
1841
|
+
})
|
|
1842
|
+
);
|
|
1843
|
+
return { blocks, latestHeight };
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
// src/token/balance.ts
|
|
1847
|
+
async function getBalance(address) {
|
|
1848
|
+
const api2 = await getApi();
|
|
1849
|
+
assert(api2, "API not initialized");
|
|
1850
|
+
const account = (await api2.query.system.account(address)).toPrimitive();
|
|
1851
|
+
const free = BigInt(account.data.free);
|
|
1852
|
+
const reserved = BigInt(account.data.reserved);
|
|
1853
|
+
const frozen = BigInt(account.data.frozen);
|
|
1854
|
+
return {
|
|
1855
|
+
free,
|
|
1856
|
+
reserved,
|
|
1857
|
+
frozen,
|
|
1858
|
+
formatted: await formatBalanceWithTokenProperties(free)
|
|
1859
|
+
};
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
// src/account/info.ts
|
|
1863
|
+
function extractDisplayName(display) {
|
|
1864
|
+
if (!display || display === "None") return null;
|
|
1865
|
+
if (typeof display === "string") return display;
|
|
1866
|
+
if (typeof display === "object" && "Raw" in display) {
|
|
1867
|
+
return String(display.Raw);
|
|
1868
|
+
}
|
|
1869
|
+
return null;
|
|
1870
|
+
}
|
|
1871
|
+
async function getAccountInfo(address) {
|
|
1872
|
+
const api2 = await getApi();
|
|
1873
|
+
assert(api2, "API not initialized");
|
|
1874
|
+
const [accountData, balance, identity] = await Promise.all([
|
|
1875
|
+
api2.query.system.account(address),
|
|
1876
|
+
getBalance(address),
|
|
1877
|
+
api2.query.identity.identityOf(address)
|
|
1878
|
+
]);
|
|
1879
|
+
const nonce = accountData.toPrimitive().nonce;
|
|
1880
|
+
const identityHuman = identity.toHuman();
|
|
1881
|
+
return {
|
|
1882
|
+
address,
|
|
1883
|
+
nonce,
|
|
1884
|
+
balance,
|
|
1885
|
+
displayName: extractDisplayName(identityHuman?.info?.display)
|
|
1886
|
+
};
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1559
1889
|
// src/compute/agreement.ts
|
|
1560
1890
|
function buildFee(fee) {
|
|
1561
1891
|
return {
|
|
@@ -1563,10 +1893,22 @@ function buildFee(fee) {
|
|
|
1563
1893
|
computeRate: toAtomicPaliAmount(fee?.computeRate ?? "0")
|
|
1564
1894
|
};
|
|
1565
1895
|
}
|
|
1896
|
+
var NO_GUARDIAN_GROUP = `0x${"00".repeat(32)}`;
|
|
1897
|
+
function buildComputeMetadata(metadata) {
|
|
1898
|
+
if (!metadata) return null;
|
|
1899
|
+
const encoder = new TextEncoder();
|
|
1900
|
+
return {
|
|
1901
|
+
name: Array.from(encoder.encode(metadata.name)),
|
|
1902
|
+
description: Array.from(encoder.encode(metadata.description)),
|
|
1903
|
+
storeType: metadata.storeType,
|
|
1904
|
+
groupId: metadata.groupId ?? NO_GUARDIAN_GROUP
|
|
1905
|
+
};
|
|
1906
|
+
}
|
|
1566
1907
|
async function createAgreement(contract, account, oracle_quore_id = void 0) {
|
|
1567
1908
|
const api2 = await getApi();
|
|
1568
1909
|
if (!api2) throw new Error("Api not initialized");
|
|
1569
|
-
const
|
|
1910
|
+
const onChainContract = { currencyId: "Native", ...contract };
|
|
1911
|
+
const tx = api2.tx["compute"]["agreement"](onChainContract, oracle_quore_id ?? null);
|
|
1570
1912
|
const opts = {
|
|
1571
1913
|
compute: {
|
|
1572
1914
|
daType: 1,
|
|
@@ -1580,11 +1922,7 @@ async function createAgreement(contract, account, oracle_quore_id = void 0) {
|
|
|
1580
1922
|
opts
|
|
1581
1923
|
);
|
|
1582
1924
|
if (!tx_result.isError) {
|
|
1583
|
-
const agreementCreatedEvent = tx_result.events
|
|
1584
|
-
(event) => {
|
|
1585
|
-
return event.event.section === "compute" && event.event.method === "AgreementCreated";
|
|
1586
|
-
}
|
|
1587
|
-
);
|
|
1925
|
+
const agreementCreatedEvent = findEvent(tx_result.events, "compute", "AgreementCreated");
|
|
1588
1926
|
if (agreementCreatedEvent) {
|
|
1589
1927
|
debugLog("Agreement data:", agreementCreatedEvent.event.data.toString());
|
|
1590
1928
|
return {
|
|
@@ -1599,6 +1937,17 @@ async function createAgreement(contract, account, oracle_quore_id = void 0) {
|
|
|
1599
1937
|
}
|
|
1600
1938
|
return { blockNumber, index: index ?? 0, hash };
|
|
1601
1939
|
}
|
|
1940
|
+
async function invokeAgreement(agreementId, input, account, opts) {
|
|
1941
|
+
const api2 = await getApi();
|
|
1942
|
+
if (!api2) throw new Error("Api not initialized");
|
|
1943
|
+
const tx = api2.tx["compute"]["invoke"](
|
|
1944
|
+
agreementId,
|
|
1945
|
+
input.guardians,
|
|
1946
|
+
input.cipher,
|
|
1947
|
+
{ Inline: { data: Array.from(input.data) } }
|
|
1948
|
+
);
|
|
1949
|
+
return signAndSend(tx, account, opts);
|
|
1950
|
+
}
|
|
1602
1951
|
async function createSimpleAgreement() {
|
|
1603
1952
|
const guardianIds = (await getGuardianAddress()).slice(0, 3).map((g) => g.address);
|
|
1604
1953
|
assert(guardianIds.length === 3, "Not enough guardians to create agreement");
|
|
@@ -1628,6 +1977,17 @@ async function createSimpleAgreement() {
|
|
|
1628
1977
|
// src/compute/data.ts
|
|
1629
1978
|
async function dataContract(params, account) {
|
|
1630
1979
|
const plaintextCipher = "Plaintext";
|
|
1980
|
+
assert(
|
|
1981
|
+
params.url === void 0 !== (params.data === void 0),
|
|
1982
|
+
"dataContract requires exactly one of `url` or `data`"
|
|
1983
|
+
);
|
|
1984
|
+
const input = params.url !== void 0 ? { Url: { url: Array.from(new TextEncoder().encode(params.url)) } } : {
|
|
1985
|
+
Inline: {
|
|
1986
|
+
data: Array.from(
|
|
1987
|
+
typeof params.data === "string" ? new TextEncoder().encode(params.data) : params.data
|
|
1988
|
+
)
|
|
1989
|
+
}
|
|
1990
|
+
};
|
|
1631
1991
|
const computeStep = {
|
|
1632
1992
|
cipher: plaintextCipher,
|
|
1633
1993
|
computerIndices: params.guardians.map((_, i) => i),
|
|
@@ -1635,14 +1995,11 @@ async function dataContract(params, account) {
|
|
|
1635
1995
|
deadline: params.deadline ?? 0,
|
|
1636
1996
|
confidentiality: { Trusted: params.trustIndex ?? 0 },
|
|
1637
1997
|
feeFunction: null,
|
|
1638
|
-
input
|
|
1639
|
-
Url: {
|
|
1640
|
-
url: Array.from(new TextEncoder().encode(params.url))
|
|
1641
|
-
}
|
|
1642
|
-
},
|
|
1998
|
+
input,
|
|
1643
1999
|
program: {
|
|
1644
2000
|
NativeData: "DaFalse"
|
|
1645
|
-
}
|
|
2001
|
+
},
|
|
2002
|
+
metadata: buildComputeMetadata(params.metadata)
|
|
1646
2003
|
};
|
|
1647
2004
|
const contract = {
|
|
1648
2005
|
contractType: "Dormant",
|
|
@@ -1655,6 +2012,157 @@ async function dataContract(params, account) {
|
|
|
1655
2012
|
return createAgreement(contract, account);
|
|
1656
2013
|
}
|
|
1657
2014
|
|
|
2015
|
+
// src/compute/fees.ts
|
|
2016
|
+
async function readMillisecondsPerBlock() {
|
|
2017
|
+
const api2 = await getApi();
|
|
2018
|
+
assert(api2, "Api not initialized");
|
|
2019
|
+
const expectedBlockTime = api2.consts.babe?.expectedBlockTime;
|
|
2020
|
+
if (expectedBlockTime) {
|
|
2021
|
+
return BigInt(expectedBlockTime.toString());
|
|
2022
|
+
}
|
|
2023
|
+
const minimumPeriod = api2.consts.timestamp?.minimumPeriod;
|
|
2024
|
+
assert(minimumPeriod, "Cannot determine block time: neither babe.expectedBlockTime nor timestamp.minimumPeriod exists");
|
|
2025
|
+
return BigInt(minimumPeriod.toString()) * 2n;
|
|
2026
|
+
}
|
|
2027
|
+
async function getFeeParams() {
|
|
2028
|
+
const api2 = await getApi();
|
|
2029
|
+
assert(api2, "Api not initialized");
|
|
2030
|
+
assert(
|
|
2031
|
+
api2.query.compute?.maxDaStorageSize,
|
|
2032
|
+
"compute.maxDaStorageSize does not exist on this runtime: the connected chain predates metered compute, and has no fee floor. Check PALLIORA_WS points at a current node."
|
|
2033
|
+
);
|
|
2034
|
+
const [maxDaStorageSize, providerStorageRate, thresholdDecryptionFee, millisecondsPerBlock] = await Promise.all([
|
|
2035
|
+
api2.query.compute.maxDaStorageSize(),
|
|
2036
|
+
api2.query.compute.providerStorageRate(),
|
|
2037
|
+
api2.query.compute.thresholdDecryptionFee(),
|
|
2038
|
+
readMillisecondsPerBlock()
|
|
2039
|
+
]);
|
|
2040
|
+
return {
|
|
2041
|
+
maxDaStorageSize: BigInt(maxDaStorageSize.toString()),
|
|
2042
|
+
providerStorageRate: BigInt(providerStorageRate.toString()),
|
|
2043
|
+
thresholdDecryptionFee: BigInt(thresholdDecryptionFee.toString()),
|
|
2044
|
+
millisecondsPerBlock
|
|
2045
|
+
};
|
|
2046
|
+
}
|
|
2047
|
+
async function estimateMinFee(input) {
|
|
2048
|
+
const api2 = await getApi();
|
|
2049
|
+
assert(api2, "Api not initialized");
|
|
2050
|
+
const params = await getFeeParams();
|
|
2051
|
+
const resultFee = params.maxDaStorageSize * params.providerStorageRate;
|
|
2052
|
+
let inputFee = 0n;
|
|
2053
|
+
if (input.inputContractId) {
|
|
2054
|
+
const contract = (await api2.query.compute.contracts(input.inputContractId)).toJSON();
|
|
2055
|
+
if (contract) {
|
|
2056
|
+
inputFee = BigInt(String(contract["usagePrice"] ?? contract["usage_price"] ?? 0));
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
const offeredComponent = toAtomicPaliAmount(input.computeRate) * params.millisecondsPerBlock;
|
|
2060
|
+
return {
|
|
2061
|
+
resultFee,
|
|
2062
|
+
inputFee,
|
|
2063
|
+
thresholdDecryptionFee: params.thresholdDecryptionFee,
|
|
2064
|
+
offeredComponent,
|
|
2065
|
+
minFee: resultFee + inputFee + params.thresholdDecryptionFee + offeredComponent
|
|
2066
|
+
};
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
// src/compute/encryptedInference.ts
|
|
2070
|
+
import { edwardsToMontgomeryPub as edwardsToMontgomeryPub2 } from "@noble/curves/ed25519";
|
|
2071
|
+
|
|
2072
|
+
// src/crypto/random.ts
|
|
2073
|
+
function generateRandomBytes(length = 32) {
|
|
2074
|
+
const bytes = new Uint8Array(length);
|
|
2075
|
+
const cr = globalThis.crypto;
|
|
2076
|
+
if (!cr || typeof cr.getRandomValues !== "function") {
|
|
2077
|
+
throw new Error(
|
|
2078
|
+
"crypto.getRandomValues is not available. Ensure you're running in a supported environment (browser or Node.js 18+)."
|
|
2079
|
+
);
|
|
2080
|
+
}
|
|
2081
|
+
cr.getRandomValues(bytes);
|
|
2082
|
+
return bytes;
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
// src/compute/encryptedInference.ts
|
|
2086
|
+
async function encryptedInferenceSubscription(params, account) {
|
|
2087
|
+
const computeStep = {
|
|
2088
|
+
cipher: "Plaintext",
|
|
2089
|
+
computerIndices: params.guardians.map((_, i) => i),
|
|
2090
|
+
...buildFee(params.fee),
|
|
2091
|
+
deadline: params.deadline ?? 0,
|
|
2092
|
+
confidentiality: { Trusted: 0 },
|
|
2093
|
+
feeFunction: null,
|
|
2094
|
+
input: null,
|
|
2095
|
+
program: { NativeExecute: "Inference" }
|
|
2096
|
+
};
|
|
2097
|
+
const contract = {
|
|
2098
|
+
contractType: "Dormant",
|
|
2099
|
+
guardians: params.guardians,
|
|
2100
|
+
preCheck: null,
|
|
2101
|
+
compute: computeStep,
|
|
2102
|
+
postCheck: null,
|
|
2103
|
+
resultCipher: "Plaintext"
|
|
2104
|
+
};
|
|
2105
|
+
return createAgreement(contract, account);
|
|
2106
|
+
}
|
|
2107
|
+
async function encryptedInferenceSubscriptionInvocation(params, encAccount, account) {
|
|
2108
|
+
const api2 = await getApi();
|
|
2109
|
+
if (!api2) throw new Error("Api not initialized");
|
|
2110
|
+
const inputBytes = typeof params.input === "string" ? new TextEncoder().encode(params.input) : params.input;
|
|
2111
|
+
const { encoded: cyphtxt, ikm } = testCrypt(
|
|
2112
|
+
params.guardianInfo.tauParams,
|
|
2113
|
+
params.guardianInfo.aggKey
|
|
2114
|
+
);
|
|
2115
|
+
const sharedKey = gen_stretched_key(hexToUint8Array(ikm));
|
|
2116
|
+
const { ciphertext, nonce } = encrypt2(inputBytes, sharedKey);
|
|
2117
|
+
const cyphtxtBytes = hexToUint8Array(cyphtxt);
|
|
2118
|
+
const groupPkBytes = hexToUint8Array(params.guardianInfo.groupPk);
|
|
2119
|
+
const tauParamsBytes = hexToUint8Array(params.guardianInfo.tauParams);
|
|
2120
|
+
const tx = api2.tx["dataAvailability"]["daccComputeRequest"](
|
|
2121
|
+
edwardsToMontgomeryPub2(encAccount.publicKey),
|
|
2122
|
+
nonce,
|
|
2123
|
+
Array.from(ciphertext),
|
|
2124
|
+
params.guardians[0],
|
|
2125
|
+
Array.from(cyphtxtBytes),
|
|
2126
|
+
Array.from(groupPkBytes),
|
|
2127
|
+
Array.from(tauParamsBytes),
|
|
2128
|
+
params.guardians
|
|
2129
|
+
);
|
|
2130
|
+
const idHex = params.agreementId.startsWith("0x") ? params.agreementId.slice(2) : params.agreementId;
|
|
2131
|
+
const opts = {
|
|
2132
|
+
compute: {
|
|
2133
|
+
da_type: 4,
|
|
2134
|
+
agreement: [Buffer.from(idHex, "hex")],
|
|
2135
|
+
verification: 0,
|
|
2136
|
+
compute: 1
|
|
2137
|
+
}
|
|
2138
|
+
};
|
|
2139
|
+
return signAndSend(tx, account, opts);
|
|
2140
|
+
}
|
|
2141
|
+
async function encryptedInferenceCompute(params, encAccount, account) {
|
|
2142
|
+
const subscription = await encryptedInferenceSubscription(
|
|
2143
|
+
{
|
|
2144
|
+
guardians: params.guardians,
|
|
2145
|
+
fee: params.fee,
|
|
2146
|
+
deadline: params.deadline
|
|
2147
|
+
},
|
|
2148
|
+
account
|
|
2149
|
+
);
|
|
2150
|
+
if (!subscription.agreementId) {
|
|
2151
|
+
throw new Error("Subscription creation did not return an agreement ID");
|
|
2152
|
+
}
|
|
2153
|
+
const invocation = await encryptedInferenceSubscriptionInvocation(
|
|
2154
|
+
{
|
|
2155
|
+
agreementId: subscription.agreementId,
|
|
2156
|
+
input: params.input,
|
|
2157
|
+
guardians: params.guardians,
|
|
2158
|
+
guardianInfo: params.guardianInfo
|
|
2159
|
+
},
|
|
2160
|
+
encAccount,
|
|
2161
|
+
account
|
|
2162
|
+
);
|
|
2163
|
+
return { subscription, invocation };
|
|
2164
|
+
}
|
|
2165
|
+
|
|
1658
2166
|
// src/compute/inference.ts
|
|
1659
2167
|
async function inferenceCompute(params, account) {
|
|
1660
2168
|
const inputData = typeof params.input === "string" ? Array.from(new TextEncoder().encode(params.input)) : Array.from(params.input);
|
|
@@ -1737,7 +2245,7 @@ async function getGuardianParticipants() {
|
|
|
1737
2245
|
upcomingGuardians
|
|
1738
2246
|
};
|
|
1739
2247
|
} finally {
|
|
1740
|
-
|
|
2248
|
+
await disconnectApi();
|
|
1741
2249
|
}
|
|
1742
2250
|
}
|
|
1743
2251
|
|
|
@@ -1769,17 +2277,177 @@ async function simpleCompute(params, account) {
|
|
|
1769
2277
|
return createAgreement(contract, account);
|
|
1770
2278
|
}
|
|
1771
2279
|
|
|
1772
|
-
// src/
|
|
1773
|
-
function
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
)
|
|
2280
|
+
// src/compute/stored.ts
|
|
2281
|
+
async function storedCompute(params, account) {
|
|
2282
|
+
assert(!!params.programContractId, "storedCompute requires a programContractId");
|
|
2283
|
+
assert(!!params.inputContractId, "storedCompute requires an inputContractId");
|
|
2284
|
+
const plaintextCipher = "Plaintext";
|
|
2285
|
+
const computeStep = {
|
|
2286
|
+
cipher: plaintextCipher,
|
|
2287
|
+
computerIndices: params.guardians.map((_, i) => i),
|
|
2288
|
+
...buildFee(params.fee),
|
|
2289
|
+
deadline: params.deadline ?? 0,
|
|
2290
|
+
confidentiality: { Trusted: params.trustIndex ?? 0 },
|
|
2291
|
+
feeFunction: null,
|
|
2292
|
+
input: { ContractId: { id: params.inputContractId } },
|
|
2293
|
+
program: { ContractId: { id: params.programContractId } },
|
|
2294
|
+
metadata: buildComputeMetadata(params.metadata)
|
|
2295
|
+
};
|
|
2296
|
+
const contract = {
|
|
2297
|
+
contractType: "Active",
|
|
2298
|
+
guardians: params.guardians,
|
|
2299
|
+
preCheck: null,
|
|
2300
|
+
compute: computeStep,
|
|
2301
|
+
postCheck: null,
|
|
2302
|
+
resultCipher: plaintextCipher
|
|
2303
|
+
};
|
|
2304
|
+
return createAgreement(contract, account);
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
// src/costEstimation/client.ts
|
|
2308
|
+
var CostEstimationError = class extends Error {
|
|
2309
|
+
constructor(message, status) {
|
|
2310
|
+
super(message);
|
|
2311
|
+
this.status = status;
|
|
2312
|
+
this.name = "CostEstimationError";
|
|
1780
2313
|
}
|
|
1781
|
-
|
|
1782
|
-
|
|
2314
|
+
};
|
|
2315
|
+
async function request(method, path2, body) {
|
|
2316
|
+
const url = `${getCostEstimatorUrl()}${path2}`;
|
|
2317
|
+
debugLog(`cost estimation service: ${method} ${url}`, body);
|
|
2318
|
+
const res = await fetch(url, {
|
|
2319
|
+
method,
|
|
2320
|
+
headers: body !== void 0 ? { "Content-Type": "application/json" } : void 0,
|
|
2321
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
2322
|
+
});
|
|
2323
|
+
const text = await res.text();
|
|
2324
|
+
const data = text ? JSON.parse(text) : void 0;
|
|
2325
|
+
if (!res.ok) {
|
|
2326
|
+
const message = data && typeof data === "object" && "error" in data ? String(data.error) : `cost estimation service returned ${res.status}`;
|
|
2327
|
+
throw new CostEstimationError(message, res.status);
|
|
2328
|
+
}
|
|
2329
|
+
return data;
|
|
2330
|
+
}
|
|
2331
|
+
var costEstimationClient = {
|
|
2332
|
+
get: (path2) => request("GET", path2),
|
|
2333
|
+
post: (path2, body) => request("POST", path2, body)
|
|
2334
|
+
};
|
|
2335
|
+
|
|
2336
|
+
// src/costEstimation/estimate.ts
|
|
2337
|
+
function toGuardianEntry(raw) {
|
|
2338
|
+
return {
|
|
2339
|
+
address: raw.address,
|
|
2340
|
+
pubKey: raw.pubKey,
|
|
2341
|
+
feeThreshold: BigInt(raw.feeThreshold)
|
|
2342
|
+
};
|
|
2343
|
+
}
|
|
2344
|
+
function toEstimateResult(raw) {
|
|
2345
|
+
return {
|
|
2346
|
+
predictedDurationMs: raw.predictedDurationMs,
|
|
2347
|
+
auctionedRate: BigInt(raw.auctionedRate),
|
|
2348
|
+
estimatedCost: BigInt(raw.estimatedCost),
|
|
2349
|
+
guardians: raw.guardians.map(toGuardianEntry)
|
|
2350
|
+
};
|
|
2351
|
+
}
|
|
2352
|
+
function toEstimateStatusResponse(raw) {
|
|
2353
|
+
if (raw.status === "completed") {
|
|
2354
|
+
return { status: "completed", auctionId: raw.auctionId, result: toEstimateResult(raw.result) };
|
|
2355
|
+
}
|
|
2356
|
+
return raw;
|
|
2357
|
+
}
|
|
2358
|
+
async function startEstimate(params) {
|
|
2359
|
+
return costEstimationClient.post("/estimate", params);
|
|
2360
|
+
}
|
|
2361
|
+
async function getEstimateResult(estimateId) {
|
|
2362
|
+
const raw = await costEstimationClient.get(
|
|
2363
|
+
`/estimates/${encodeURIComponent(estimateId)}`
|
|
2364
|
+
);
|
|
2365
|
+
return toEstimateStatusResponse(raw);
|
|
2366
|
+
}
|
|
2367
|
+
async function waitForEstimate(params, options = {}) {
|
|
2368
|
+
const { intervalMs = 5e3, timeoutMs = 6e4 } = options;
|
|
2369
|
+
const { estimateId } = await startEstimate(params);
|
|
2370
|
+
const deadline = Date.now() + timeoutMs;
|
|
2371
|
+
for (; ; ) {
|
|
2372
|
+
const status = await getEstimateResult(estimateId);
|
|
2373
|
+
if (status.status !== "pending") {
|
|
2374
|
+
return { estimateId, status };
|
|
2375
|
+
}
|
|
2376
|
+
const remaining = deadline - Date.now();
|
|
2377
|
+
if (remaining <= 0) {
|
|
2378
|
+
throw new Error(
|
|
2379
|
+
`waitForEstimate: estimate ${estimateId} still pending after ${timeoutMs}ms`
|
|
2380
|
+
);
|
|
2381
|
+
}
|
|
2382
|
+
await sleep(Math.min(intervalMs, remaining));
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
function sleep(ms) {
|
|
2386
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
// src/costEstimation/auction.ts
|
|
2390
|
+
import { u8aToHex } from "@polkadot/util";
|
|
2391
|
+
function toAuctionWinner(raw) {
|
|
2392
|
+
return { guardian: raw.guardian, rate: BigInt(raw.rate) };
|
|
2393
|
+
}
|
|
2394
|
+
async function listOpenAuctions() {
|
|
2395
|
+
const { auctions } = await costEstimationClient.get("/auctions");
|
|
2396
|
+
return auctions;
|
|
2397
|
+
}
|
|
2398
|
+
async function listGuardianAuctions(guardianAddress) {
|
|
2399
|
+
const { auctions } = await costEstimationClient.get(
|
|
2400
|
+
`/guardians/${encodeURIComponent(guardianAddress)}/auctions`
|
|
2401
|
+
);
|
|
2402
|
+
return auctions;
|
|
2403
|
+
}
|
|
2404
|
+
async function getAuction(auctionId) {
|
|
2405
|
+
const raw = await costEstimationClient.get(
|
|
2406
|
+
`/auctions/${encodeURIComponent(auctionId)}`
|
|
2407
|
+
);
|
|
2408
|
+
return {
|
|
2409
|
+
auctionId: raw.auctionId,
|
|
2410
|
+
contractId: raw.contractId,
|
|
2411
|
+
guardians: raw.guardians,
|
|
2412
|
+
deadline: raw.deadline,
|
|
2413
|
+
resolved: raw.resolved,
|
|
2414
|
+
winner: raw.winner ? toAuctionWinner(raw.winner) : void 0
|
|
2415
|
+
};
|
|
2416
|
+
}
|
|
2417
|
+
async function listResolvedGuardianAuctions(guardianAddress) {
|
|
2418
|
+
const { auctions } = await costEstimationClient.get(
|
|
2419
|
+
`/guardians/${encodeURIComponent(guardianAddress)}/auctions?resolved=true`
|
|
2420
|
+
);
|
|
2421
|
+
return auctions.map((a) => ({
|
|
2422
|
+
auctionId: a.auctionId,
|
|
2423
|
+
contractId: a.contractId,
|
|
2424
|
+
guardians: a.guardians,
|
|
2425
|
+
deadline: a.deadline,
|
|
2426
|
+
winner: toAuctionWinner(a.winner)
|
|
2427
|
+
}));
|
|
2428
|
+
}
|
|
2429
|
+
async function submitAuctionBid(auctionId, rate, guardian) {
|
|
2430
|
+
const signature = u8aToHex(guardian.sign(`${auctionId}:${rate}`));
|
|
2431
|
+
await costEstimationClient.post(
|
|
2432
|
+
`/auctions/${encodeURIComponent(auctionId)}/bid`,
|
|
2433
|
+
{ guardian: guardian.address, rate, signature }
|
|
2434
|
+
);
|
|
2435
|
+
}
|
|
2436
|
+
|
|
2437
|
+
// src/costEstimation/webhook.ts
|
|
2438
|
+
import { u8aToHex as u8aToHex2 } from "@polkadot/util";
|
|
2439
|
+
async function registerGuardianWebhook(url, guardian) {
|
|
2440
|
+
const signature = u8aToHex2(guardian.sign(`webhook:${url}`));
|
|
2441
|
+
await costEstimationClient.post(
|
|
2442
|
+
`/guardians/${encodeURIComponent(guardian.address)}/webhook`,
|
|
2443
|
+
{ url, signature }
|
|
2444
|
+
);
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2447
|
+
// src/costEstimation/health.ts
|
|
2448
|
+
async function healthCheck() {
|
|
2449
|
+
const { status } = await costEstimationClient.get("/health");
|
|
2450
|
+
return status === "ok";
|
|
1783
2451
|
}
|
|
1784
2452
|
|
|
1785
2453
|
// src/da/register.ts
|
|
@@ -1792,7 +2460,7 @@ async function writeMetadata(account, name, description, ref, price, dataType, l
|
|
|
1792
2460
|
const api2 = await getApi();
|
|
1793
2461
|
assert(api2, "Failed to get API connection");
|
|
1794
2462
|
debugLog(`Registering metadata for ${name} at ${formatPaliAmount(price)}`);
|
|
1795
|
-
const
|
|
2463
|
+
const request2 = api2.tx.dataAvailability.daccRegisterData(
|
|
1796
2464
|
nameBytes,
|
|
1797
2465
|
descriptionBytes,
|
|
1798
2466
|
blobRef,
|
|
@@ -1801,7 +2469,7 @@ async function writeMetadata(account, name, description, ref, price, dataType, l
|
|
|
1801
2469
|
ownerBytes,
|
|
1802
2470
|
groupId
|
|
1803
2471
|
);
|
|
1804
|
-
const hash = await signAndSend(
|
|
2472
|
+
const hash = await signAndSend(request2, account);
|
|
1805
2473
|
debugLog(`Metadata registration transaction sent with hash: ${hash.hash}`);
|
|
1806
2474
|
return hash;
|
|
1807
2475
|
}
|
|
@@ -1811,13 +2479,7 @@ async function registerDataAgreement(account, params) {
|
|
|
1811
2479
|
);
|
|
1812
2480
|
const cipher = params.cipher ?? "Plaintext";
|
|
1813
2481
|
const resultCipher = params.resultCipher ?? "Plaintext";
|
|
1814
|
-
const
|
|
1815
|
-
const computeMetadata = params.metadata ? {
|
|
1816
|
-
name: Array.from(encoder.encode(params.metadata.name)),
|
|
1817
|
-
description: Array.from(encoder.encode(params.metadata.description)),
|
|
1818
|
-
storeType: params.metadata.storeType,
|
|
1819
|
-
groupId: params.metadata.groupId
|
|
1820
|
-
} : null;
|
|
2482
|
+
const computeMetadata = buildComputeMetadata(params.metadata);
|
|
1821
2483
|
const computeStep = {
|
|
1822
2484
|
cipher,
|
|
1823
2485
|
computerIndices: params.guardians.map((_, i) => i),
|
|
@@ -1853,7 +2515,7 @@ async function runAgent(account, agentRef, nonce, ciphertext, tdParams, pkBytes,
|
|
|
1853
2515
|
const baseModelTuple = [baseModel.blockNumber, baseModel.index];
|
|
1854
2516
|
const api2 = await getApi();
|
|
1855
2517
|
assert(api2, "Failed to get API connection");
|
|
1856
|
-
const
|
|
2518
|
+
const request2 = api2.tx.dataAvailability.daccRunAgent(
|
|
1857
2519
|
agentRefTuple,
|
|
1858
2520
|
Array.from(nonce),
|
|
1859
2521
|
Array.from(ciphertext),
|
|
@@ -1873,7 +2535,7 @@ async function runAgent(account, agentRef, nonce, ciphertext, tdParams, pkBytes,
|
|
|
1873
2535
|
agreement: [agreementId]
|
|
1874
2536
|
}
|
|
1875
2537
|
};
|
|
1876
|
-
const hash = await signAndSend(
|
|
2538
|
+
const hash = await signAndSend(request2, account, opts);
|
|
1877
2539
|
debugLog(`Run agent transaction sent with hash: ${hash.hash}`);
|
|
1878
2540
|
return hash;
|
|
1879
2541
|
}
|
|
@@ -1905,8 +2567,8 @@ async function submitTEData(account, data, chosenGuardians, tau_params, agg_key,
|
|
|
1905
2567
|
});
|
|
1906
2568
|
const api2 = await getApi();
|
|
1907
2569
|
assert(api2, "Failed to get API connection");
|
|
1908
|
-
const
|
|
1909
|
-
const hash = await signAndSend(
|
|
2570
|
+
const request2 = await api2.tx.dataAvailability.submitData(modelSubmit);
|
|
2571
|
+
const hash = await signAndSend(request2, account, DEFAULT_EMPTY_PAYLOAD);
|
|
1910
2572
|
debugLog(`TE data availability transaction sent with hash: ${hash.hash}`);
|
|
1911
2573
|
return hash;
|
|
1912
2574
|
}
|
|
@@ -1919,8 +2581,8 @@ async function submitTEDataWithCipher(account, data, chosenGuardians, tau_params
|
|
|
1919
2581
|
const ciphertextHex = "0x" + Array.from(ciphertext).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1920
2582
|
const api2 = await getApi();
|
|
1921
2583
|
assert(api2, "Failed to get API connection");
|
|
1922
|
-
const
|
|
1923
|
-
const ref = await signAndSend(
|
|
2584
|
+
const request2 = await api2.tx.dataAvailability.submitData(ciphertextHex);
|
|
2585
|
+
const ref = await signAndSend(request2, account, DEFAULT_EMPTY_PAYLOAD);
|
|
1924
2586
|
debugLog(`TE data availability transaction sent with hash: ${ref.hash}`);
|
|
1925
2587
|
return {
|
|
1926
2588
|
ref,
|
|
@@ -1955,7 +2617,7 @@ async function uploadData(options) {
|
|
|
1955
2617
|
if (filePath) {
|
|
1956
2618
|
throw new Error("uploadData: file path upload is not implemented");
|
|
1957
2619
|
} else {
|
|
1958
|
-
const storeType = type === "model" ? "Model" : type === "agent" ? "Agent" : "Dataset";
|
|
2620
|
+
const storeType = type === "model" ? "Model" : type === "agent" ? "Agent" : type === "executable" ? "Executable" : "Dataset";
|
|
1959
2621
|
const { ref: dataRef, cipher } = await submitTEDataWithCipher(
|
|
1960
2622
|
account,
|
|
1961
2623
|
ref || "",
|
|
@@ -2017,7 +2679,7 @@ async function uploadDataLegacy(options) {
|
|
|
2017
2679
|
guardianGroupInfo.aggKey,
|
|
2018
2680
|
guardianGroupInfo.groupPk
|
|
2019
2681
|
);
|
|
2020
|
-
const dtype = type === "model" ? 1 : type === "agent" ? 2 : 0;
|
|
2682
|
+
const dtype = type === "model" ? 1 : type === "agent" ? 2 : type === "executable" ? 4 : 0;
|
|
2021
2683
|
await writeMetadata(
|
|
2022
2684
|
account,
|
|
2023
2685
|
name,
|
|
@@ -2114,6 +2776,67 @@ async function withdrawStake(account) {
|
|
|
2114
2776
|
debugLog(`Unstake transaction sent with hash: ${hash.hash}`);
|
|
2115
2777
|
}
|
|
2116
2778
|
|
|
2779
|
+
// src/storage/s3.ts
|
|
2780
|
+
var S3Provider = class {
|
|
2781
|
+
constructor() {
|
|
2782
|
+
this.id = "s3";
|
|
2783
|
+
}
|
|
2784
|
+
getDeterministicUrl(hash) {
|
|
2785
|
+
return `https://${getAwsS3Bucket()}.s3.${getAwsRegion()}.amazonaws.com/Contracts/${hash}`;
|
|
2786
|
+
}
|
|
2787
|
+
async getUploadUrl(txHash, fileHash, blockNumber, expectedUrl) {
|
|
2788
|
+
const response = await fetch(`${getAuthServiceUrl()}/api/s3/auth`, {
|
|
2789
|
+
method: "POST",
|
|
2790
|
+
headers: { "Content-Type": "application/json" },
|
|
2791
|
+
body: JSON.stringify({ txHash, fileHash, blockNumber, url: expectedUrl })
|
|
2792
|
+
});
|
|
2793
|
+
if (!response.ok) {
|
|
2794
|
+
let errorMessage = response.statusText;
|
|
2795
|
+
try {
|
|
2796
|
+
const errData = await response.json();
|
|
2797
|
+
if (errData.error) errorMessage = errData.error;
|
|
2798
|
+
} catch {
|
|
2799
|
+
}
|
|
2800
|
+
throw new Error(`Auth Service failed: ${errorMessage}`);
|
|
2801
|
+
}
|
|
2802
|
+
const { presignedUrl } = await response.json();
|
|
2803
|
+
if (!presignedUrl) {
|
|
2804
|
+
throw new Error("No presignedUrl returned from Auth Service");
|
|
2805
|
+
}
|
|
2806
|
+
return presignedUrl;
|
|
2807
|
+
}
|
|
2808
|
+
async upload(url, data) {
|
|
2809
|
+
const response = await fetch(url, {
|
|
2810
|
+
method: "PUT",
|
|
2811
|
+
body: data
|
|
2812
|
+
});
|
|
2813
|
+
if (!response.ok) {
|
|
2814
|
+
throw new Error(`Storage Upload failed: ${response.statusText}`);
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
};
|
|
2818
|
+
|
|
2819
|
+
// src/storage/router.ts
|
|
2820
|
+
var StorageRouter = class {
|
|
2821
|
+
constructor() {
|
|
2822
|
+
this.providers = /* @__PURE__ */ new Map();
|
|
2823
|
+
this.register(new S3Provider());
|
|
2824
|
+
this.defaultProvider = "s3";
|
|
2825
|
+
}
|
|
2826
|
+
register(provider) {
|
|
2827
|
+
this.providers.set(provider.id, provider);
|
|
2828
|
+
}
|
|
2829
|
+
getProvider(id) {
|
|
2830
|
+
const targetId = id || this.defaultProvider;
|
|
2831
|
+
const provider = this.providers.get(targetId);
|
|
2832
|
+
if (!provider) {
|
|
2833
|
+
throw new Error(`Storage provider '${targetId}' not found`);
|
|
2834
|
+
}
|
|
2835
|
+
return provider;
|
|
2836
|
+
}
|
|
2837
|
+
};
|
|
2838
|
+
var storageRouter = new StorageRouter();
|
|
2839
|
+
|
|
2117
2840
|
// src/token/fund.ts
|
|
2118
2841
|
async function fundAccount(account, amountBaseUnits, address) {
|
|
2119
2842
|
const addr = address ? address : account.address;
|
|
@@ -2160,15 +2883,499 @@ Setting identity for account: ${account.address} as ${display}`);
|
|
|
2160
2883
|
debugLog(`Set identity transaction sent with hash: ${hash.hash}`);
|
|
2161
2884
|
}
|
|
2162
2885
|
|
|
2886
|
+
// src/indexer/client.ts
|
|
2887
|
+
var DEFAULT_BASE_URL = "http://localhost:5020";
|
|
2888
|
+
var IndexerClient = class {
|
|
2889
|
+
constructor(options = {}) {
|
|
2890
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "").replace(/\/api$/i, "");
|
|
2891
|
+
this._fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
2892
|
+
}
|
|
2893
|
+
/**
|
|
2894
|
+
* Performs a GET request against the indexer and returns the parsed JSON body.
|
|
2895
|
+
*
|
|
2896
|
+
* @throws {IndexerHttpError} When the response indicates failure (`success: false`)
|
|
2897
|
+
* or the HTTP status is not 2xx.
|
|
2898
|
+
*/
|
|
2899
|
+
async get(path2, params) {
|
|
2900
|
+
const url = new URL(`${this.baseUrl}${path2}`);
|
|
2901
|
+
if (params) {
|
|
2902
|
+
for (const [key, value] of Object.entries(params)) {
|
|
2903
|
+
if (value !== void 0 && value !== null) {
|
|
2904
|
+
url.searchParams.set(key, String(value));
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
const response = await this._fetch(url.toString(), {
|
|
2909
|
+
method: "GET",
|
|
2910
|
+
headers: { Accept: "application/json" }
|
|
2911
|
+
});
|
|
2912
|
+
const raw = await response.text();
|
|
2913
|
+
let body;
|
|
2914
|
+
try {
|
|
2915
|
+
body = raw ? JSON.parse(raw) : null;
|
|
2916
|
+
} catch {
|
|
2917
|
+
if (!response.ok) {
|
|
2918
|
+
throw new IndexerHttpError(
|
|
2919
|
+
response.status,
|
|
2920
|
+
raw || response.statusText
|
|
2921
|
+
);
|
|
2922
|
+
}
|
|
2923
|
+
throw new IndexerHttpError(
|
|
2924
|
+
response.status,
|
|
2925
|
+
`Invalid JSON response from ${url.toString()}: ${raw.slice(0, 120)}`
|
|
2926
|
+
);
|
|
2927
|
+
}
|
|
2928
|
+
if (!response.ok) {
|
|
2929
|
+
const errBody = body;
|
|
2930
|
+
throw new IndexerHttpError(
|
|
2931
|
+
response.status,
|
|
2932
|
+
errBody?.message ?? response.statusText
|
|
2933
|
+
);
|
|
2934
|
+
}
|
|
2935
|
+
return body;
|
|
2936
|
+
}
|
|
2937
|
+
};
|
|
2938
|
+
var IndexerHttpError = class extends Error {
|
|
2939
|
+
constructor(statusCode, message) {
|
|
2940
|
+
super(message);
|
|
2941
|
+
this.name = "IndexerHttpError";
|
|
2942
|
+
this.statusCode = statusCode;
|
|
2943
|
+
}
|
|
2944
|
+
};
|
|
2945
|
+
|
|
2946
|
+
// src/indexer/artefacts.ts
|
|
2947
|
+
async function getArtefacts(client, query) {
|
|
2948
|
+
return client.get("/api/artefacts", query ? { ...query } : void 0);
|
|
2949
|
+
}
|
|
2950
|
+
async function getArtefactsByStoreType(client, storeType) {
|
|
2951
|
+
const response = await getArtefacts(client);
|
|
2952
|
+
return {
|
|
2953
|
+
success: true,
|
|
2954
|
+
data: response.data.filter((item) => item.storeType === storeType)
|
|
2955
|
+
};
|
|
2956
|
+
}
|
|
2957
|
+
async function getDatasets(client) {
|
|
2958
|
+
return getArtefactsByStoreType(client, "Dataset");
|
|
2959
|
+
}
|
|
2960
|
+
async function getModels(client) {
|
|
2961
|
+
return getArtefactsByStoreType(client, "Model");
|
|
2962
|
+
}
|
|
2963
|
+
async function getAgents(client) {
|
|
2964
|
+
return getArtefactsByStoreType(client, "Agent");
|
|
2965
|
+
}
|
|
2966
|
+
async function getExecutables(client) {
|
|
2967
|
+
return getArtefactsByStoreType(client, "Executable");
|
|
2968
|
+
}
|
|
2969
|
+
async function getArtefact(client, id) {
|
|
2970
|
+
return client.get(`/api/artefact/${encodeURIComponent(id)}`);
|
|
2971
|
+
}
|
|
2972
|
+
async function getArtefactAccess(client, id, query) {
|
|
2973
|
+
return client.get(
|
|
2974
|
+
`/api/artefact/${encodeURIComponent(id)}/access`,
|
|
2975
|
+
query ? { ...query } : void 0
|
|
2976
|
+
);
|
|
2977
|
+
}
|
|
2978
|
+
function nestedContractId(value) {
|
|
2979
|
+
if (typeof value === "string") return value;
|
|
2980
|
+
if (value && typeof value === "object" && "id" in value) {
|
|
2981
|
+
const id = value.id;
|
|
2982
|
+
return typeof id === "string" ? id : void 0;
|
|
2983
|
+
}
|
|
2984
|
+
return void 0;
|
|
2985
|
+
}
|
|
2986
|
+
function isArtefactUsage(doc, artefactId) {
|
|
2987
|
+
if (!doc || doc.contractId === artefactId) return false;
|
|
2988
|
+
if (doc.inputContractId === artefactId) return true;
|
|
2989
|
+
const compute = doc.compute;
|
|
2990
|
+
const inputId = nestedContractId(compute?.input?.contractId);
|
|
2991
|
+
const programId = nestedContractId(compute?.program?.contractId);
|
|
2992
|
+
return inputId === artefactId || programId === artefactId;
|
|
2993
|
+
}
|
|
2994
|
+
async function getArtefactContracts(client, id, query) {
|
|
2995
|
+
const response = await client.get(
|
|
2996
|
+
`/api/artefact/${encodeURIComponent(id)}/contracts`,
|
|
2997
|
+
query ? { ...query } : void 0
|
|
2998
|
+
);
|
|
2999
|
+
const list = Array.isArray(response.data) ? response.data : [];
|
|
3000
|
+
const usages = list.filter((item) => isArtefactUsage(item, id));
|
|
3001
|
+
if (usages.length > 0) {
|
|
3002
|
+
return { ...response, data: usages };
|
|
3003
|
+
}
|
|
3004
|
+
const looksLikeSelfOnly = list.length > 0 && list.every((item) => item?.contractId === id);
|
|
3005
|
+
if (!looksLikeSelfOnly) {
|
|
3006
|
+
return {
|
|
3007
|
+
...response,
|
|
3008
|
+
data: list.filter((item) => item?.contractId !== id)
|
|
3009
|
+
};
|
|
3010
|
+
}
|
|
3011
|
+
const artefacts = await getArtefacts(client);
|
|
3012
|
+
return {
|
|
3013
|
+
success: true,
|
|
3014
|
+
data: (artefacts.data || []).filter(
|
|
3015
|
+
(item) => isArtefactUsage(item, id)
|
|
3016
|
+
)
|
|
3017
|
+
};
|
|
3018
|
+
}
|
|
3019
|
+
|
|
3020
|
+
// src/indexer/contracts.ts
|
|
3021
|
+
async function getContracts(client, query) {
|
|
3022
|
+
return client.get("/api/contracts", query ? { ...query } : void 0);
|
|
3023
|
+
}
|
|
3024
|
+
async function getContract(client, id) {
|
|
3025
|
+
return client.get(`/api/contract/${encodeURIComponent(id)}`);
|
|
3026
|
+
}
|
|
3027
|
+
async function getCompute(client, id) {
|
|
3028
|
+
return client.get(`/api/compute/${encodeURIComponent(id)}`);
|
|
3029
|
+
}
|
|
3030
|
+
async function getResults(client, query) {
|
|
3031
|
+
return client.get("/api/results", { contractId: query.contractId });
|
|
3032
|
+
}
|
|
3033
|
+
async function getResult(client, id) {
|
|
3034
|
+
return client.get(`/api/result/${encodeURIComponent(id)}`);
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
// src/indexer/blobs.ts
|
|
3038
|
+
async function getBlob(client, id) {
|
|
3039
|
+
return client.get(`/api/blob/${encodeURIComponent(String(id))}`);
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
// src/indexer/flow.ts
|
|
3043
|
+
function computeTime(item) {
|
|
3044
|
+
return item.indexer?.blockTime ?? 0;
|
|
3045
|
+
}
|
|
3046
|
+
function isComputeRequest(item) {
|
|
3047
|
+
return Boolean(
|
|
3048
|
+
item.jobId || item.orchestrator || item.resultTx || item.computeReward || item.decryptionFee
|
|
3049
|
+
);
|
|
3050
|
+
}
|
|
3051
|
+
function normalizeComputes(compute) {
|
|
3052
|
+
if (!compute) return [];
|
|
3053
|
+
const list = Array.isArray(compute) ? compute : Array.isArray(compute.computes) ? compute.computes : [compute];
|
|
3054
|
+
return [...list].filter(isComputeRequest).sort((a, b) => computeTime(a) - computeTime(b));
|
|
3055
|
+
}
|
|
3056
|
+
function resultToCompute(result) {
|
|
3057
|
+
const indexer = result.indexer;
|
|
3058
|
+
return {
|
|
3059
|
+
...result,
|
|
3060
|
+
jobId: result.resultId,
|
|
3061
|
+
contractId: result.contractId,
|
|
3062
|
+
orchestrator: result.submitor,
|
|
3063
|
+
resultTx: indexer ? {
|
|
3064
|
+
blockHeight: indexer.blockHeight,
|
|
3065
|
+
extrinsicIndex: indexer.extrinsicIndex,
|
|
3066
|
+
blockHash: indexer.blockHash,
|
|
3067
|
+
hash: indexer.blockHash
|
|
3068
|
+
} : { hash: result.resultId },
|
|
3069
|
+
computeReward: result.feeBreakdown?.submitorFee?.amount,
|
|
3070
|
+
fee: result.feeBreakdown?.resultFee,
|
|
3071
|
+
decryptionFee: result.feeBreakdown?.thresholdDecryptionFee,
|
|
3072
|
+
indexer
|
|
3073
|
+
};
|
|
3074
|
+
}
|
|
3075
|
+
function mergeComputes(fromResults, fromCompute) {
|
|
3076
|
+
if (fromResults.length === 0) return fromCompute;
|
|
3077
|
+
const ids = new Set(
|
|
3078
|
+
fromResults.flatMap((item) => [item.jobId, item.contractId].filter(Boolean))
|
|
3079
|
+
);
|
|
3080
|
+
const extras = fromCompute.filter(
|
|
3081
|
+
(item) => !ids.has(item.jobId ?? "") && !ids.has(item.contractId ?? "")
|
|
3082
|
+
);
|
|
3083
|
+
return normalizeComputes([...fromResults, ...extras]);
|
|
3084
|
+
}
|
|
3085
|
+
function withParties(agreement) {
|
|
3086
|
+
if (agreement.parties?.length) return agreement;
|
|
3087
|
+
const guardians = agreement.guardians;
|
|
3088
|
+
if (Array.isArray(guardians) && guardians.length) {
|
|
3089
|
+
return { ...agreement, parties: guardians };
|
|
3090
|
+
}
|
|
3091
|
+
return agreement;
|
|
3092
|
+
}
|
|
3093
|
+
function deriveContractStatus(agreement, compute) {
|
|
3094
|
+
if (!agreement) return "\u2014";
|
|
3095
|
+
const computes = normalizeComputes(compute);
|
|
3096
|
+
if (computes.length === 0) {
|
|
3097
|
+
return (agreement.responses?.length ?? 0) > 0 ? "ACCEPTED" : "PENDING";
|
|
3098
|
+
}
|
|
3099
|
+
if (computes.every((item) => !!item.resultTx)) return "COMPLETED";
|
|
3100
|
+
return "PROCESSING";
|
|
3101
|
+
}
|
|
3102
|
+
function buildContractPhases(agreement, compute) {
|
|
3103
|
+
const computes = normalizeComputes(compute);
|
|
3104
|
+
const latest = computes[computes.length - 1] ?? null;
|
|
3105
|
+
const settledCount = computes.filter((item) => !!item.resultTx).length;
|
|
3106
|
+
const status = deriveContractStatus(agreement, computes);
|
|
3107
|
+
const phase1Active = !!agreement;
|
|
3108
|
+
const phase1Complete = status === "ACCEPTED" || status === "PROCESSING" || status === "COMPLETED";
|
|
3109
|
+
const phase2Active = computes.length > 0;
|
|
3110
|
+
const allSettled = computes.length > 0 && settledCount === computes.length;
|
|
3111
|
+
const phase5Complete = status === "COMPLETED";
|
|
3112
|
+
const requestsJson = computes.map((item) => {
|
|
3113
|
+
const { _id: _ignored, ...rest } = item;
|
|
3114
|
+
return rest;
|
|
3115
|
+
});
|
|
3116
|
+
return [
|
|
3117
|
+
{
|
|
3118
|
+
id: "phase-1",
|
|
3119
|
+
title: "Phase 1: Contract Agreement",
|
|
3120
|
+
status: agreement ? `RESPONSES (${agreement.responses?.length ?? 0})` : "\u2014",
|
|
3121
|
+
description: "Established once and reused by every compute request in this session.",
|
|
3122
|
+
json: agreement ? {
|
|
3123
|
+
contractId: agreement.contractId,
|
|
3124
|
+
creator: agreement.creator,
|
|
3125
|
+
fee: agreement.fee,
|
|
3126
|
+
creationTime: agreement.creationTime,
|
|
3127
|
+
parties: agreement.parties,
|
|
3128
|
+
responses: agreement.responses,
|
|
3129
|
+
indexer: agreement.indexer,
|
|
3130
|
+
computeTx: agreement.computeTx
|
|
3131
|
+
} : {},
|
|
3132
|
+
active: phase1Active,
|
|
3133
|
+
complete: phase1Complete,
|
|
3134
|
+
pending: phase1Active && !phase1Complete
|
|
3135
|
+
},
|
|
3136
|
+
{
|
|
3137
|
+
id: "phase-2",
|
|
3138
|
+
title: "Phase 2: Compute Request",
|
|
3139
|
+
status: phase2Active ? `${computes.length} SUBMITTED` : "PENDING",
|
|
3140
|
+
description: "Each iteration submits a compute request that is broadcast to all guardians.",
|
|
3141
|
+
json: { requestCount: computes.length, requests: requestsJson },
|
|
3142
|
+
active: phase2Active,
|
|
3143
|
+
complete: phase2Active,
|
|
3144
|
+
pending: phase1Complete && !phase2Active
|
|
3145
|
+
},
|
|
3146
|
+
{
|
|
3147
|
+
id: "phase-3",
|
|
3148
|
+
title: "Phase 3: Guardian Execution",
|
|
3149
|
+
status: allSettled ? `${settledCount}/${computes.length} RESULT_SUBMITTED` : phase2Active ? `${settledCount}/${computes.length} PROCESSING` : "PENDING",
|
|
3150
|
+
description: "One guardian claims each request, executes compute, and submits the result on-chain.",
|
|
3151
|
+
json: latest?.resultTx ? {
|
|
3152
|
+
jobId: latest.jobId,
|
|
3153
|
+
contractId: latest.contractId,
|
|
3154
|
+
orchestrator: latest.orchestrator,
|
|
3155
|
+
resultTx: latest.resultTx,
|
|
3156
|
+
settledCount,
|
|
3157
|
+
requestCount: computes.length
|
|
3158
|
+
} : { settledCount, requestCount: computes.length },
|
|
3159
|
+
active: phase2Active,
|
|
3160
|
+
complete: allSettled,
|
|
3161
|
+
pending: phase2Active && !allSettled
|
|
3162
|
+
},
|
|
3163
|
+
{
|
|
3164
|
+
id: "phase-4",
|
|
3165
|
+
title: "Phase 4: Fee Distribution",
|
|
3166
|
+
status: allSettled ? `${settledCount}/${computes.length} SETTLED` : phase2Active ? "PROCESSING" : "PENDING",
|
|
3167
|
+
description: "Executor reward is paid per completed request. TD fee was locked once at agreement.",
|
|
3168
|
+
json: allSettled ? {
|
|
3169
|
+
requestCount: computes.length,
|
|
3170
|
+
settledCount,
|
|
3171
|
+
computeReward: latest?.computeReward,
|
|
3172
|
+
decryptionFee: latest?.decryptionFee,
|
|
3173
|
+
fee: latest?.fee
|
|
3174
|
+
} : { requestCount: computes.length, settledCount },
|
|
3175
|
+
active: allSettled,
|
|
3176
|
+
complete: allSettled,
|
|
3177
|
+
pending: phase2Active && !allSettled
|
|
3178
|
+
},
|
|
3179
|
+
{
|
|
3180
|
+
id: "phase-5",
|
|
3181
|
+
title: "Phase 5: Close Out",
|
|
3182
|
+
status: phase5Complete ? "SETTLED" : phase1Complete ? "PENDING" : "\u2014",
|
|
3183
|
+
description: "User sends closeout, guardians clean up, remaining funds are refunded.",
|
|
3184
|
+
json: {
|
|
3185
|
+
requestCount: computes.length,
|
|
3186
|
+
settledCount,
|
|
3187
|
+
finalStatus: phase5Complete ? "SETTLED" : status
|
|
3188
|
+
},
|
|
3189
|
+
active: phase5Complete,
|
|
3190
|
+
complete: phase5Complete,
|
|
3191
|
+
pending: phase1Complete && !phase5Complete
|
|
3192
|
+
}
|
|
3193
|
+
];
|
|
3194
|
+
}
|
|
3195
|
+
async function getContractFlow(client, id) {
|
|
3196
|
+
const [agreementResponse, compute, results] = await Promise.all([
|
|
3197
|
+
getContract(client, id),
|
|
3198
|
+
getCompute(client, id).then((response) => response.data).catch((err) => {
|
|
3199
|
+
if (err instanceof IndexerHttpError && err.statusCode === 404) return null;
|
|
3200
|
+
throw err;
|
|
3201
|
+
}),
|
|
3202
|
+
getResults(client, { contractId: id }).then((response) => response.data).catch((err) => {
|
|
3203
|
+
if (err instanceof IndexerHttpError && err.statusCode === 404) return [];
|
|
3204
|
+
throw err;
|
|
3205
|
+
})
|
|
3206
|
+
]);
|
|
3207
|
+
const agreement = withParties(agreementResponse.data);
|
|
3208
|
+
const computes = mergeComputes(
|
|
3209
|
+
(results ?? []).map(resultToCompute),
|
|
3210
|
+
normalizeComputes(compute)
|
|
3211
|
+
);
|
|
3212
|
+
const latest = computes[computes.length - 1] ?? null;
|
|
3213
|
+
return {
|
|
3214
|
+
success: true,
|
|
3215
|
+
data: {
|
|
3216
|
+
agreement,
|
|
3217
|
+
compute: latest,
|
|
3218
|
+
computes,
|
|
3219
|
+
results: results ?? [],
|
|
3220
|
+
status: deriveContractStatus(agreement, computes),
|
|
3221
|
+
phases: buildContractPhases(agreement, computes)
|
|
3222
|
+
}
|
|
3223
|
+
};
|
|
3224
|
+
}
|
|
3225
|
+
function blobHeightsFromArtefact(artefact) {
|
|
3226
|
+
const refs = artefact.blobRefs;
|
|
3227
|
+
if (!Array.isArray(refs)) return [];
|
|
3228
|
+
const heights = [];
|
|
3229
|
+
for (const ref of refs) {
|
|
3230
|
+
const raw = Array.isArray(ref) ? ref[0] : ref;
|
|
3231
|
+
const height = typeof raw === "number" ? raw : Number(raw);
|
|
3232
|
+
if (Number.isFinite(height)) heights.push(height);
|
|
3233
|
+
}
|
|
3234
|
+
return heights;
|
|
3235
|
+
}
|
|
3236
|
+
async function getArtefactFlow(client, id, accessQuery) {
|
|
3237
|
+
const artefactResponse = await getArtefact(client, id);
|
|
3238
|
+
const artefact = artefactResponse.data;
|
|
3239
|
+
let access = [];
|
|
3240
|
+
try {
|
|
3241
|
+
const accessResponse = await getArtefactAccess(client, id, accessQuery);
|
|
3242
|
+
access = Array.isArray(accessResponse.data) ? accessResponse.data : [];
|
|
3243
|
+
} catch (err) {
|
|
3244
|
+
if (!(err instanceof IndexerHttpError && err.statusCode === 404)) throw err;
|
|
3245
|
+
}
|
|
3246
|
+
const blobs = [];
|
|
3247
|
+
for (const height of blobHeightsFromArtefact(artefact)) {
|
|
3248
|
+
try {
|
|
3249
|
+
const blobResponse = await getBlob(client, height);
|
|
3250
|
+
if (blobResponse.data) blobs.push(blobResponse.data);
|
|
3251
|
+
} catch (err) {
|
|
3252
|
+
if (err instanceof IndexerHttpError && err.statusCode === 404) continue;
|
|
3253
|
+
throw err;
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
return {
|
|
3257
|
+
success: true,
|
|
3258
|
+
data: { artefact, access, blobs }
|
|
3259
|
+
};
|
|
3260
|
+
}
|
|
3261
|
+
|
|
3262
|
+
// src/indexer/blocks.ts
|
|
3263
|
+
async function getBlocks(client, query) {
|
|
3264
|
+
return client.get("/api/blocks", query ? { ...query } : void 0);
|
|
3265
|
+
}
|
|
3266
|
+
|
|
3267
|
+
// src/indexer/calls.ts
|
|
3268
|
+
async function getCall(client, query) {
|
|
3269
|
+
return client.get("/api/call", { ...query });
|
|
3270
|
+
}
|
|
3271
|
+
async function getCallMetadata(client, query) {
|
|
3272
|
+
return client.get("/api/call-metadata", { ...query });
|
|
3273
|
+
}
|
|
3274
|
+
async function getCallArgs(client, query) {
|
|
3275
|
+
return client.get("/api/call-args", { ...query });
|
|
3276
|
+
}
|
|
3277
|
+
|
|
3278
|
+
// src/indexer/transfers.ts
|
|
3279
|
+
async function getTransfers(client, query) {
|
|
3280
|
+
return client.get("/api/transfers", query ? { ...query } : void 0);
|
|
3281
|
+
}
|
|
3282
|
+
|
|
3283
|
+
// src/indexer/extrinsics.ts
|
|
3284
|
+
async function getExtrinsics(client, query) {
|
|
3285
|
+
if (!query) {
|
|
3286
|
+
return client.get("/api/extrinsics");
|
|
3287
|
+
}
|
|
3288
|
+
const { signed_only, ...rest } = query;
|
|
3289
|
+
const params = { ...rest };
|
|
3290
|
+
if (signed_only !== void 0) {
|
|
3291
|
+
params.signed_only = signed_only === true || signed_only === "true" ? "true" : "false";
|
|
3292
|
+
}
|
|
3293
|
+
return client.get("/api/extrinsics", params);
|
|
3294
|
+
}
|
|
3295
|
+
async function getExtrinsic(client, indexOrHash) {
|
|
3296
|
+
return client.get(`/api/extrinsic/${encodeURIComponent(indexOrHash)}`);
|
|
3297
|
+
}
|
|
3298
|
+
|
|
3299
|
+
// src/indexer/addresses.ts
|
|
3300
|
+
async function getAddresses(client) {
|
|
3301
|
+
return client.get("/api/addresses");
|
|
3302
|
+
}
|
|
3303
|
+
async function getAddress(client, address) {
|
|
3304
|
+
return client.get(`/api/address/${encodeURIComponent(address)}`);
|
|
3305
|
+
}
|
|
3306
|
+
|
|
3307
|
+
// src/indexer/guardians.ts
|
|
3308
|
+
function displayNameForAccount(groups, account) {
|
|
3309
|
+
for (const group of groups) {
|
|
3310
|
+
const addresses = group.guardians ?? [];
|
|
3311
|
+
const names = group.guardianNames ?? [];
|
|
3312
|
+
const index = addresses.indexOf(account);
|
|
3313
|
+
if (index === -1) continue;
|
|
3314
|
+
const rawName = names[index];
|
|
3315
|
+
if (typeof rawName === "string" && rawName.length > 0) return rawName;
|
|
3316
|
+
}
|
|
3317
|
+
return null;
|
|
3318
|
+
}
|
|
3319
|
+
function uniqueGuardians(groups) {
|
|
3320
|
+
const seen = /* @__PURE__ */ new Map();
|
|
3321
|
+
for (const group of groups) {
|
|
3322
|
+
const addresses = group.guardians ?? [];
|
|
3323
|
+
const names = group.guardianNames ?? [];
|
|
3324
|
+
for (let i = 0; i < addresses.length; i++) {
|
|
3325
|
+
const account = addresses[i];
|
|
3326
|
+
if (!account || seen.has(account)) continue;
|
|
3327
|
+
const rawName = names[i];
|
|
3328
|
+
seen.set(account, typeof rawName === "string" && rawName.length > 0 ? rawName : null);
|
|
3329
|
+
}
|
|
3330
|
+
}
|
|
3331
|
+
return Array.from(seen, ([account, displayName]) => ({ account, displayName }));
|
|
3332
|
+
}
|
|
3333
|
+
async function guardianGroupsOrEmpty(client, query) {
|
|
3334
|
+
try {
|
|
3335
|
+
const response = await getGuardianGroups(client, query);
|
|
3336
|
+
return response.data ?? [];
|
|
3337
|
+
} catch (err) {
|
|
3338
|
+
if (err instanceof IndexerHttpError && err.statusCode === 404) {
|
|
3339
|
+
return [];
|
|
3340
|
+
}
|
|
3341
|
+
throw err;
|
|
3342
|
+
}
|
|
3343
|
+
}
|
|
3344
|
+
async function getGuardianGroups(client, query) {
|
|
3345
|
+
return client.get("/api/guardian-groups", query ? { ...query } : void 0);
|
|
3346
|
+
}
|
|
3347
|
+
async function getGuardians(client) {
|
|
3348
|
+
const groups = await guardianGroupsOrEmpty(client);
|
|
3349
|
+
return { success: true, data: uniqueGuardians(groups) };
|
|
3350
|
+
}
|
|
3351
|
+
async function getGuardian(client, account) {
|
|
3352
|
+
const groups = await guardianGroupsOrEmpty(client, { guardian: account });
|
|
3353
|
+
return {
|
|
3354
|
+
success: true,
|
|
3355
|
+
data: {
|
|
3356
|
+
account,
|
|
3357
|
+
displayName: displayNameForAccount(groups, account)
|
|
3358
|
+
}
|
|
3359
|
+
};
|
|
3360
|
+
}
|
|
3361
|
+
async function getGuardianGroup(client, id) {
|
|
3362
|
+
return client.get(`/api/guardian-group/${encodeURIComponent(id)}`);
|
|
3363
|
+
}
|
|
3364
|
+
|
|
3365
|
+
// src/indexer/access.ts
|
|
3366
|
+
async function getAccess(client, query) {
|
|
3367
|
+
return client.get("/api/access", query ? { ...query } : void 0);
|
|
3368
|
+
}
|
|
3369
|
+
|
|
2163
3370
|
// src/rotateKeys.ts
|
|
2164
3371
|
import bs583 from "bs58";
|
|
2165
3372
|
import assert3 from "assert";
|
|
2166
3373
|
async function rotateAndSetKeys(account) {
|
|
2167
3374
|
const api2 = await getApi();
|
|
2168
3375
|
assert3(api2, "API not initialized");
|
|
2169
|
-
debugLog(`Rotating session keys for ${account.meta.name} on ${
|
|
3376
|
+
debugLog(`Rotating session keys for ${account.meta.name} on ${getProvider().endpoint}`);
|
|
2170
3377
|
const newKeys = await api2.rpc.author.rotateKeys();
|
|
2171
|
-
debugLog(`${account.meta.name} rotated keys on ${
|
|
3378
|
+
debugLog(`${account.meta.name} rotated keys on ${getProvider().endpoint}:`, newKeys?.toHex?.() ?? newKeys);
|
|
2172
3379
|
const setKeysTx = api2.tx.session.setKeys(newKeys, []);
|
|
2173
3380
|
const hash = await signAndSend(setKeysTx, account);
|
|
2174
3381
|
debugLog(`Rotate session transaction sent with hash: ${hash.hash}`);
|
|
@@ -2196,7 +3403,7 @@ import { hexToU8a as hexToU8a2, isHex as isHex2, stringToU8a } from "@polkadot/u
|
|
|
2196
3403
|
import { base64Decode, decodeAddress as decodeAddress2, ed25519PairFromSeed as ed25519FromSeed2, encodeAddress, ethereumEncode as ethereumEncode2, hdEthereum, keyExtractSuri, keyFromPath as keyFromPath2, mnemonicToLegacySeed, mnemonicToMiniSecret, secp256k1PairFromSeed as secp256k1FromSeed2, sr25519PairFromSeed as sr25519FromSeed2 } from "@polkadot/util-crypto";
|
|
2197
3404
|
|
|
2198
3405
|
// node_modules/.pnpm/@polkadot+keyring@13.5.9_@polkadot+util-crypto@13.5.9_@polkadot+util@13.5.9__@polkadot+util@13.5.9/node_modules/@polkadot/keyring/pair/index.js
|
|
2199
|
-
import { objectSpread as objectSpread2, u8aConcat as u8aConcat2, u8aEmpty, u8aEq as u8aEq2, u8aToHex, u8aToU8a } from "@polkadot/util";
|
|
3406
|
+
import { objectSpread as objectSpread2, u8aConcat as u8aConcat2, u8aEmpty, u8aEq as u8aEq2, u8aToHex as u8aToHex3, u8aToU8a } from "@polkadot/util";
|
|
2200
3407
|
import { blake2AsU8a, ed25519PairFromSeed as ed25519FromSeed, ed25519Sign, ethereumEncode, keccakAsU8a, keyExtractPath, keyFromPath, secp256k1Compress, secp256k1Expand, secp256k1PairFromSeed as secp256k1FromSeed, secp256k1Sign, signatureVerify, sr25519PairFromSeed as sr25519FromSeed, sr25519Sign, sr25519VrfSign, sr25519VrfVerify } from "@polkadot/util-crypto";
|
|
2201
3408
|
|
|
2202
3409
|
// node_modules/.pnpm/@polkadot+keyring@13.5.9_@polkadot+util-crypto@13.5.9_@polkadot+util@13.5.9__@polkadot+util@13.5.9/node_modules/@polkadot/keyring/pair/decode.js
|
|
@@ -2366,7 +3573,7 @@ function createPair({ toSS58, type }, { publicKey, secretKey }, meta = {}, encod
|
|
|
2366
3573
|
return u8aConcat2(options.withType ? TYPE_PREFIX[type] : SIG_TYPE_NONE, TYPE_SIGNATURE[type](u8aToU8a(message), { publicKey, secretKey }));
|
|
2367
3574
|
},
|
|
2368
3575
|
toJson: (passphrase) => {
|
|
2369
|
-
const address = ["ecdsa", "ethereum"].includes(type) ? publicKey.length === 20 ?
|
|
3576
|
+
const address = ["ecdsa", "ethereum"].includes(type) ? publicKey.length === 20 ? u8aToHex3(publicKey) : u8aToHex3(secp256k1Compress(publicKey)) : encodeAddress3();
|
|
2370
3577
|
return pairToJson(type, { address, meta }, recode(passphrase), !!passphrase);
|
|
2371
3578
|
},
|
|
2372
3579
|
unlock: (passphrase) => {
|
|
@@ -2399,7 +3606,7 @@ function createPair({ toSS58, type }, { publicKey, secretKey }, meta = {}, encod
|
|
|
2399
3606
|
var DEV_PHRASE = "bottom drive obey lake curtain smoke basket hold race lonely fit walk";
|
|
2400
3607
|
|
|
2401
3608
|
// node_modules/.pnpm/@polkadot+keyring@13.5.9_@polkadot+util-crypto@13.5.9_@polkadot+util@13.5.9__@polkadot+util@13.5.9/node_modules/@polkadot/keyring/pairs.js
|
|
2402
|
-
import { isHex, isU8a, u8aToHex as
|
|
3609
|
+
import { isHex, isU8a, u8aToHex as u8aToHex4, u8aToU8a as u8aToU8a2 } from "@polkadot/util";
|
|
2403
3610
|
import { decodeAddress } from "@polkadot/util-crypto";
|
|
2404
3611
|
var _map;
|
|
2405
3612
|
var Pairs = class {
|
|
@@ -2416,7 +3623,7 @@ var Pairs = class {
|
|
|
2416
3623
|
get(address) {
|
|
2417
3624
|
const pair = __privateGet(this, _map)[decodeAddress(address).toString()];
|
|
2418
3625
|
if (!pair) {
|
|
2419
|
-
throw new Error(`Unable to retrieve keypair '${isU8a(address) || isHex(address) ?
|
|
3626
|
+
throw new Error(`Unable to retrieve keypair '${isU8a(address) || isHex(address) ? u8aToHex4(u8aToU8a2(address)) : address}'`);
|
|
2420
3627
|
}
|
|
2421
3628
|
return pair;
|
|
2422
3629
|
}
|
|
@@ -2651,28 +3858,33 @@ export {
|
|
|
2651
3858
|
API_TYPES,
|
|
2652
3859
|
AccountSourceType,
|
|
2653
3860
|
ApiPromise2 as ApiPromise,
|
|
3861
|
+
COMPUTE_TYPES,
|
|
3862
|
+
CostEstimationError,
|
|
2654
3863
|
CryptoType,
|
|
2655
|
-
DEBUG,
|
|
2656
3864
|
DEFAULT_COMPUTE_PAYLOAD,
|
|
2657
3865
|
DEFAULT_EMPTY_PAYLOAD,
|
|
2658
3866
|
FileFromMetadataRef,
|
|
2659
3867
|
HttpProvider,
|
|
3868
|
+
IndexerClient,
|
|
3869
|
+
IndexerHttpError,
|
|
2660
3870
|
Keyring3 as Keyring,
|
|
2661
3871
|
MCryptFs,
|
|
2662
3872
|
MCryptFsReader,
|
|
2663
3873
|
MCryptFsWriter,
|
|
3874
|
+
NO_GUARDIAN_GROUP,
|
|
2664
3875
|
PALI_DECIMALS,
|
|
2665
3876
|
PALI_SYMBOL,
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
TX_WAIT_FINALIZATION,
|
|
3877
|
+
S3Provider,
|
|
3878
|
+
StorageRouter,
|
|
2669
3879
|
WsProvider3 as WsProvider,
|
|
2670
3880
|
addStake,
|
|
2671
3881
|
base64ToUint8Array,
|
|
3882
|
+
buildComputeMetadata,
|
|
3883
|
+
buildContractPhases,
|
|
2672
3884
|
buildFee,
|
|
2673
3885
|
clearTokenCache,
|
|
2674
|
-
configure,
|
|
2675
3886
|
createAccount,
|
|
3887
|
+
createAccountFromMagicLink,
|
|
2676
3888
|
createAgreement,
|
|
2677
3889
|
createGuardianGroup,
|
|
2678
3890
|
createGuardianGroupAndWatch,
|
|
@@ -2683,11 +3895,18 @@ export {
|
|
|
2683
3895
|
decodeField,
|
|
2684
3896
|
decodePowersOfTau,
|
|
2685
3897
|
decrypt,
|
|
3898
|
+
deriveContractStatus,
|
|
3899
|
+
disconnectApi,
|
|
2686
3900
|
encrypt as ecncryptTest,
|
|
2687
3901
|
encodeCiphertext,
|
|
2688
3902
|
encrypt2 as encrypt,
|
|
3903
|
+
encryptedInferenceCompute,
|
|
3904
|
+
encryptedInferenceSubscription,
|
|
3905
|
+
encryptedInferenceSubscriptionInvocation,
|
|
3906
|
+
estimateMinFee,
|
|
2689
3907
|
fetchAndDecodeExtrinsic,
|
|
2690
3908
|
fetchTokenProperties,
|
|
3909
|
+
findEvent,
|
|
2691
3910
|
formatBalanceWithTokenProperties,
|
|
2692
3911
|
formatPaliAmount,
|
|
2693
3912
|
fromAtomicPaliAmount,
|
|
@@ -2695,28 +3914,88 @@ export {
|
|
|
2695
3914
|
gen_shared_key,
|
|
2696
3915
|
gen_stretched_key,
|
|
2697
3916
|
generateRandomBytes,
|
|
3917
|
+
getAccess,
|
|
3918
|
+
getAccountInfo,
|
|
3919
|
+
getActiveGuardians,
|
|
3920
|
+
getAddress,
|
|
3921
|
+
getAddresses,
|
|
3922
|
+
getAgents,
|
|
2698
3923
|
getAgreementCreatedRequestId,
|
|
2699
3924
|
getApi,
|
|
3925
|
+
getArtefact,
|
|
3926
|
+
getArtefactAccess,
|
|
3927
|
+
getArtefactContracts,
|
|
3928
|
+
getArtefactFlow,
|
|
3929
|
+
getArtefacts,
|
|
3930
|
+
getArtefactsByStoreType,
|
|
3931
|
+
getAuction,
|
|
3932
|
+
getAuthServiceUrl,
|
|
3933
|
+
getAwsRegion,
|
|
3934
|
+
getAwsS3Bucket,
|
|
3935
|
+
getBalance,
|
|
3936
|
+
getBlob,
|
|
3937
|
+
getBlocks,
|
|
2700
3938
|
getCachedTokenProperties,
|
|
3939
|
+
getCall,
|
|
3940
|
+
getCallArgs,
|
|
3941
|
+
getCallMetadata,
|
|
3942
|
+
getCompute,
|
|
3943
|
+
getContract,
|
|
3944
|
+
getContractFlow,
|
|
3945
|
+
getContractInfo,
|
|
3946
|
+
getContracts,
|
|
3947
|
+
getCostEstimatorUrl,
|
|
3948
|
+
getDatasets,
|
|
2701
3949
|
getEncKeyring,
|
|
3950
|
+
getEstimateResult,
|
|
3951
|
+
getExecutables,
|
|
3952
|
+
getExtrinsic,
|
|
3953
|
+
getExtrinsics,
|
|
3954
|
+
getFeeParams,
|
|
2702
3955
|
getFileMetadataCall,
|
|
3956
|
+
getGuardian,
|
|
2703
3957
|
getGuardianAddress,
|
|
3958
|
+
getGuardianGroup,
|
|
3959
|
+
getGuardianGroupInfo,
|
|
3960
|
+
getGuardianGroups,
|
|
2704
3961
|
getGuardianList,
|
|
2705
3962
|
getGuardianNwParams,
|
|
2706
3963
|
getGuardianParticipants,
|
|
3964
|
+
getGuardians,
|
|
2707
3965
|
getKeyring,
|
|
3966
|
+
getLatestBlocks,
|
|
3967
|
+
getModels,
|
|
3968
|
+
getPallioraRpcUrl,
|
|
3969
|
+
getPallioraWs,
|
|
3970
|
+
getProvider,
|
|
3971
|
+
getResult,
|
|
3972
|
+
getResults,
|
|
3973
|
+
getTransfers,
|
|
3974
|
+
healthCheck,
|
|
2708
3975
|
hexToUint8Array,
|
|
2709
3976
|
inferenceCompute,
|
|
3977
|
+
init,
|
|
3978
|
+
invokeAgreement,
|
|
3979
|
+
isArtefactUsage,
|
|
3980
|
+
isDebug,
|
|
3981
|
+
isInitialized,
|
|
2710
3982
|
joinGuardian,
|
|
2711
3983
|
joinIdleStaker,
|
|
2712
3984
|
joinValidator,
|
|
3985
|
+
listGuardianAuctions,
|
|
3986
|
+
listOpenAuctions,
|
|
3987
|
+
listResolvedGuardianAuctions,
|
|
2713
3988
|
newStake,
|
|
3989
|
+
normalizeComputes,
|
|
2714
3990
|
pairFromPrivateKeyHex,
|
|
2715
3991
|
payoutStake,
|
|
2716
|
-
provider,
|
|
2717
3992
|
reduceStake,
|
|
2718
3993
|
registerDataAgreement,
|
|
3994
|
+
registerGuardianWebhook,
|
|
2719
3995
|
removeStake,
|
|
3996
|
+
resetConfig,
|
|
3997
|
+
resultToCompute,
|
|
3998
|
+
retrySignAndSend,
|
|
2720
3999
|
rotateAndSetKeys,
|
|
2721
4000
|
runAgent,
|
|
2722
4001
|
scanForBlockEvent,
|
|
@@ -2724,6 +4003,10 @@ export {
|
|
|
2724
4003
|
setWorker,
|
|
2725
4004
|
signAndSend,
|
|
2726
4005
|
simpleCompute,
|
|
4006
|
+
startEstimate,
|
|
4007
|
+
storageRouter,
|
|
4008
|
+
storedCompute,
|
|
4009
|
+
submitAuctionBid,
|
|
2727
4010
|
submitData,
|
|
2728
4011
|
submitTEData,
|
|
2729
4012
|
submitTEDataWithCipher,
|
|
@@ -2735,6 +4018,9 @@ export {
|
|
|
2735
4018
|
uploadData,
|
|
2736
4019
|
uploadDataLegacy,
|
|
2737
4020
|
utilCrypto,
|
|
4021
|
+
waitForEstimate,
|
|
4022
|
+
waitForNextBlock,
|
|
4023
|
+
waitsForFinalization,
|
|
2738
4024
|
wasmCrypto,
|
|
2739
4025
|
watchForSubmissionReceipt,
|
|
2740
4026
|
withdrawStake,
|