@palliora.org/chainsdk 0.1.0 → 0.2.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.js CHANGED
@@ -220,12 +220,144 @@ var API_TYPES = {
220
220
  extra: "CheckAppIdExtra",
221
221
  types: "CheckAppIdTypes"
222
222
  },
223
+ FeePayload: {
224
+ compute: "u128",
225
+ guardian: "u128",
226
+ verifier: "u128"
227
+ },
228
+ SilentThresholdParams: {
229
+ td_params: "Vec<u8>",
230
+ pk_bytes: "Vec<u8>",
231
+ tau_params: "Vec<u8>"
232
+ },
233
+ ThresholdAlgos: {
234
+ _enum: {
235
+ SilentThreshold: "SilentThresholdParams"
236
+ }
237
+ },
238
+ ChaCha20Poly1305Params: {
239
+ nonce: "[u8; 12]"
240
+ },
241
+ Aes256GcmParams: {
242
+ nonce: "[u8; 12]"
243
+ },
244
+ SymmetricAlgos: {
245
+ _enum: {
246
+ ChaCha20Poly1305: "ChaCha20Poly1305Params",
247
+ Aes256Gcm: "Aes256GcmParams"
248
+ }
249
+ },
250
+ CipherSuiteEncrypted: {
251
+ threshold: "ThresholdAlgos",
252
+ symmetric: "SymmetricAlgos"
253
+ },
254
+ CipherSuite: {
255
+ _enum: {
256
+ Plaintext: "Null",
257
+ Encrypted: "CipherSuiteEncrypted"
258
+ }
259
+ },
260
+ ConfidentialityLevel: {
261
+ _enum: ["Trusted", "TEE", "FHE", "SMPC"]
262
+ },
263
+ NativeExecuteDA: {
264
+ _enum: ["Inference"]
265
+ },
266
+ NativeDataDA: {
267
+ _enum: ["DaFalse", "DaTrue"]
268
+ },
269
+ DAInputInline: {
270
+ data: "Vec<u8>"
271
+ },
272
+ DAInputChainTransaction: {
273
+ block_number: "u64",
274
+ extrinsic_index: "u32"
275
+ },
276
+ DAInputIpfs: {
277
+ cid: "Vec<u8>",
278
+ size: "u64"
279
+ },
280
+ DAInputUrl: {
281
+ url: "Vec<u8>",
282
+ size: "u64",
283
+ hash: "Option<Vec<u8>>"
284
+ },
285
+ DAInput: {
286
+ _enum: {
287
+ Inline: "DAInputInline",
288
+ ChainTransaction: "DAInputChainTransaction",
289
+ Ipfs: "DAInputIpfs",
290
+ Url: "DAInputUrl",
291
+ NativeExecute: "NativeExecuteDA",
292
+ NativeData: "NativeDataDA"
293
+ }
294
+ },
295
+ ContractType: {
296
+ _enum: {
297
+ Dormant: "Dormant",
298
+ Active: "Active"
299
+ }
300
+ },
301
+ StoreType: {
302
+ _enum: {
303
+ Dataset: "Dataset",
304
+ Model: "Model",
305
+ Agent: "Agent",
306
+ Other: "Other"
307
+ }
308
+ },
309
+ ComputeMetadata: {
310
+ name: "Vec<u8>",
311
+ description: "Vec<u8>",
312
+ store_type: "StoreType",
313
+ group_id: "H256"
314
+ },
315
+ ComputeInfo: {
316
+ cipher: "CipherSuite",
317
+ computer_indices: "Vec<u32>",
318
+ fees: "u128",
319
+ deadline: "u64",
320
+ confidentiality: "ConfidentialityLevel",
321
+ fee_function: "Option<u8>",
322
+ program_env: "Option<Vec<u8>>",
323
+ input: "DAInput",
324
+ program: "DAInput",
325
+ metadata: "Option<ComputeMetadata>"
326
+ },
327
+ Contract: {
328
+ contract_type: "ContractType",
329
+ guardians: "Vec<AccountId>",
330
+ pre_check: "Option<ComputeInfo>",
331
+ compute: "ComputeInfo",
332
+ post_check: "Option<ComputeInfo>",
333
+ result_cipher: "CipherSuite"
334
+ },
335
+ AgreementInfo: {
336
+ status: "AgreementStatus",
337
+ creator: "AccountId",
338
+ index: "u32"
339
+ },
223
340
  ComputePayload: {
224
341
  da_type: "u8",
225
342
  agreement: "Option<BoundedVec<[u8; 32], 10>>",
226
343
  verification: "u8",
227
344
  compute: "u8"
228
345
  },
346
+ ComputePrefs: {
347
+ trusted: "bool",
348
+ tee: "bool",
349
+ mpc: "bool",
350
+ fhe: "bool",
351
+ zkp: "bool"
352
+ },
353
+ GuardianPrefs: {
354
+ pubKey: "[u8; 32]",
355
+ guardian: "bool",
356
+ verifier: "bool",
357
+ compute: "bool",
358
+ computePrefs: "Option<ComputePrefs>",
359
+ feeThreshold: "u128"
360
+ },
229
361
  BlockLengthColumns: "Compact<u32>",
230
362
  BlockLengthRows: "Compact<u32>",
231
363
  BlockLength: {
@@ -599,10 +731,6 @@ function configure(opts) {
599
731
  }
600
732
 
601
733
  // src/utils/helper.ts
602
- var tokenToBigint = (arg) => {
603
- const val = typeof arg === "bigint" ? arg : BigInt(arg);
604
- return val * 10n ** 15n;
605
- };
606
734
  function hexToUint8Array(hex) {
607
735
  if (hex.length % 2 !== 0) {
608
736
  throw new Error("Invalid hex string");
@@ -653,8 +781,23 @@ var debugLog = (message, ...optionalParams) => {
653
781
  };
654
782
 
655
783
  // src/utils/token.ts
656
- import { formatBalance } from "@polkadot/util";
784
+ import { formatUnits, parseUnits } from "viem";
785
+ var PALI_SYMBOL = "PALI";
786
+ var PALI_DECIMALS = 18;
657
787
  var tokenCache = null;
788
+ var toAtomicPaliAmount = (amount) => {
789
+ const normalizedAmount = String(amount).trim();
790
+ if (!normalizedAmount) {
791
+ throw new Error("Token amount cannot be empty");
792
+ }
793
+ return parseUnits(normalizedAmount, PALI_DECIMALS);
794
+ };
795
+ var fromAtomicPaliAmount = (amount) => {
796
+ return formatUnits(amount, PALI_DECIMALS);
797
+ };
798
+ var formatPaliAmount = (amount, symbol = PALI_SYMBOL) => {
799
+ return `${fromAtomicPaliAmount(amount)} ${symbol}`;
800
+ };
658
801
  async function fetchTokenProperties() {
659
802
  if (tokenCache) {
660
803
  return tokenCache;
@@ -663,13 +806,12 @@ async function fetchTokenProperties() {
663
806
  const systemProperties = (await (await getApi())?.rpc.system.properties())?.toHuman();
664
807
  assert(systemProperties, "Failed to fetch system properties from RPC");
665
808
  const tokenProperties = {
666
- symbol: (systemProperties?.tokenSymbol || ["UNIT"])[0],
667
- decimals: Number((systemProperties?.tokenDecimals || ["18"])[0])
809
+ symbol: (systemProperties?.tokenSymbol || [PALI_SYMBOL])[0],
810
+ decimals: Number((systemProperties?.tokenDecimals || [String(PALI_DECIMALS)])[0])
668
811
  };
669
812
  tokenCache = tokenProperties;
670
813
  return tokenProperties;
671
814
  } catch (error) {
672
- console.error("Failed to fetch token properties:", error);
673
815
  throw error;
674
816
  }
675
817
  }
@@ -681,20 +823,12 @@ function clearTokenCache() {
681
823
  }
682
824
  async function formatBalanceWithTokenProperties(balance) {
683
825
  const tokenProperties = await fetchTokenProperties();
684
- if (!tokenProperties) {
685
- throw new Error(
686
- "Token properties not yet cached. Call fetchTokenProperties first."
687
- );
688
- }
689
- return formatBalance(balance, {
690
- decimals: tokenProperties.decimals,
691
- withSi: true,
692
- withUnit: tokenProperties.symbol
693
- });
826
+ return `${formatUnits(typeof balance === "bigint" ? balance : BigInt(balance), tokenProperties.decimals)} ${tokenProperties.symbol}`;
694
827
  }
828
+ var tokenToBigint = toAtomicPaliAmount;
695
829
 
696
830
  // src/chain/singleton.ts
697
- import { ApiPromise, Keyring as Keyring2, WsProvider as WsProvider2 } from "@polkadot/api";
831
+ import { ApiPromise, Keyring as Keyring2 } from "@polkadot/api";
698
832
 
699
833
  // src/chain/wsProvider.ts
700
834
  import { WsProvider } from "@polkadot/api";
@@ -702,128 +836,13 @@ var provider = new WsProvider(PALLIORA_WS, 1e4);
702
836
 
703
837
  // src/chain/singleton.ts
704
838
  import { waitReady as waitReady2 } from "@polkadot/wasm-crypto";
705
- var wsProvider = null;
706
839
  var api = null;
707
840
  var keyring = null;
708
841
  var encKeyring = null;
709
- var RpcApi = class {
710
- constructor() {
711
- this.isConnected = false;
712
- this.isConnecting = false;
713
- this.error = null;
714
- }
715
- /**
716
- * Establishes a connection to a node at `endpoint` and returns the singleton
717
- * API and Keyring instances.
718
- *
719
- * @param endpoint - WebSocket endpoint URL to connect to (e.g. "wss://...").
720
- * @returns A promise resolving to an object containing the singleton {@link ApiPromise}
721
- * instance and the singleton {@link Keyring} instance.
722
- *
723
- * @remarks
724
- * - If a connection already exists (`isConnected === true`) the method returns
725
- * the already-initialized instances without recreating them.
726
- * - The method sets `isConnecting` to true while establishing the connection and
727
- * clears it in a `finally` block.
728
- * - Provider and API event listeners update the instance `error` and `isConnected`
729
- * fields on runtime errors and disconnects.
730
- * - The Keyring created here uses `sr25519` keys. If the standalone `getKeyring`
731
- * helper is used elsewhere, it will additionally add a default development
732
- * account derived from the well-known dev URI `//Bob` (named "Bob default").
733
- *
734
- * @throws Will re-throw underlying errors encountered while creating the provider
735
- * or API. In that case `error` will contain the textual error message.
736
- */
737
- async connect(endpoint) {
738
- try {
739
- if (this.isConnected) {
740
- return { api, keyring };
741
- }
742
- this.isConnecting = true;
743
- this.error = null;
744
- if (!wsProvider) {
745
- wsProvider = new WsProvider2(endpoint);
746
- wsProvider.on("error", (err) => {
747
- console.error("WsProvider error:", err);
748
- this.error = "WebSocket connection error";
749
- this.isConnected = false;
750
- });
751
- wsProvider.on("disconnected", () => {
752
- console.log("WsProvider disconnected");
753
- this.isConnected = false;
754
- });
755
- }
756
- if (!api) {
757
- api = await ApiPromise.create({
758
- provider: wsProvider,
759
- rpc: API_RPC,
760
- types: API_TYPES,
761
- signedExtensions: API_EXTENSIONS
762
- });
763
- api.on("error", (err) => {
764
- console.error("API error:", err);
765
- this.error = "API error occurred";
766
- });
767
- api.on("disconnected", () => {
768
- this.isConnected = false;
769
- });
770
- }
771
- if (!keyring) {
772
- keyring = new Keyring2({ type: "sr25519" });
773
- }
774
- if (!encKeyring) {
775
- encKeyring = new Keyring2({ type: "ed25519" });
776
- }
777
- await api.isReady;
778
- this.isConnected = true;
779
- return { api, keyring };
780
- } catch (err) {
781
- console.error("Failed to connect to Polkadot:", err);
782
- this.error = err instanceof Error ? err.message : "Failed to connect to Polkadot";
783
- throw err;
784
- } finally {
785
- this.isConnecting = false;
786
- }
787
- }
788
- /**
789
- * Gracefully disconnects and nullifies the singleton API, provider and keyring
790
- * instances managed by this RpcApi instance.
791
- *
792
- * @remarks
793
- * - The method calls `api.disconnect()` and `wsProvider.disconnect()` if they
794
- * exist, then sets the internal singletons to `null` and `isConnected` to false.
795
- * - Any error during disconnect is captured in `error`.
796
- */
797
- async disconnect() {
798
- try {
799
- if (api) {
800
- await api.disconnect();
801
- api = null;
802
- }
803
- if (wsProvider) {
804
- await wsProvider.disconnect();
805
- wsProvider = null;
806
- }
807
- keyring = null;
808
- this.isConnected = false;
809
- } catch (err) {
810
- console.error("Error disconnecting:", err);
811
- this.error = err instanceof Error ? err.message : "Failed to disconnect";
812
- }
813
- }
814
- getApi() {
815
- return api;
816
- }
817
- getKeyring() {
818
- return keyring;
819
- }
820
- getEncKeyring() {
821
- return encKeyring;
822
- }
823
- };
824
- async function getApi() {
842
+ var apiListenersAttached = false;
843
+ var apiTeardownInProgress = false;
844
+ async function getApi(cb) {
825
845
  if (!provider) return;
826
- console.debug(provider.endpoint);
827
846
  if (!api) {
828
847
  api = await ApiPromise.create({
829
848
  provider,
@@ -834,14 +853,24 @@ async function getApi() {
834
853
  }
835
854
  const isNode = typeof process !== "undefined" && typeof process.exit === "function";
836
855
  const isTest = typeof process !== "undefined" && process.env?.NODE_ENV === "test";
837
- if (isNode && !isTest) {
856
+ if (isNode && !isTest && api && !apiListenersAttached) {
857
+ apiListenersAttached = true;
838
858
  api.on("error", (err) => {
839
- console.error("api error, will restart:", err);
840
- process.exit(0);
859
+ if (apiTeardownInProgress) return;
860
+ apiTeardownInProgress = true;
861
+ apiListenersAttached = false;
862
+ const currentApi = api;
863
+ api = null;
864
+ void currentApi?.disconnect().catch((disconnectErr) => {
865
+ apiTeardownInProgress = false;
866
+ console.error("api disconnect after error failed:", disconnectErr);
867
+ });
841
868
  });
842
869
  api.on("disconnected", () => {
843
- console.error("api disconnected, will restart.");
844
- process.exit(0);
870
+ api = null;
871
+ apiListenersAttached = false;
872
+ apiTeardownInProgress = false;
873
+ if (cb) cb();
845
874
  });
846
875
  }
847
876
  return api;
@@ -862,13 +891,6 @@ async function getEncKeyring() {
862
891
  }
863
892
  return encKeyring;
864
893
  }
865
- var apiInstance = null;
866
- function getRpcApi() {
867
- if (!apiInstance) {
868
- apiInstance = new RpcApi();
869
- }
870
- return apiInstance;
871
- }
872
894
 
873
895
  // src/chain/utils.ts
874
896
  import { isFunction as isFunction2 } from "@polkadot/util";
@@ -919,6 +941,7 @@ async function joinGuardian(account, prefs) {
919
941
  assert(api2, "API not initialized");
920
942
  assert(account, "Account not initialized");
921
943
  const computeOpts = prefs.compute?.split(",").map((s) => s.trim()).filter((s) => s.length > 0) || void 0;
944
+ const feeThreshold = typeof prefs.fee === "bigint" ? prefs.fee : BigInt(prefs.fee || "0");
922
945
  const guardianPrefs = {
923
946
  pubKey: account.publicKey,
924
947
  guardian: prefs.standard,
@@ -930,12 +953,13 @@ async function joinGuardian(account, prefs) {
930
953
  mpc: computeOpts?.includes("mpc") || false,
931
954
  fhe: computeOpts?.includes("fhe") || false,
932
955
  zkp: computeOpts?.includes("zkp") || false
933
- }
956
+ },
957
+ feeThreshold
934
958
  };
935
959
  debugLog(
936
960
  account.address,
937
961
  "joining as guardian with preferences:",
938
- guardianPrefs
962
+ { ...guardianPrefs, feeThreshold: formatPaliAmount(feeThreshold) }
939
963
  );
940
964
  const guardTx = api2.tx.staking.guard(guardianPrefs);
941
965
  const hash = await signAndSend(guardTx, account);
@@ -1237,18 +1261,29 @@ var FileFromMetadataRef = async (mcryptApi, metadataRef) => {
1237
1261
 
1238
1262
  // src/compute/agreement.ts
1239
1263
  import bs582 from "bs58";
1240
- async function createAgreement() {
1264
+ async function createAgreement(contract, account) {
1241
1265
  const api2 = await getApi();
1242
1266
  if (!api2) throw new Error("Api not initialized");
1243
- const tx = api2.tx.compute.agreement();
1244
- const guardians = await getGuardianList();
1245
- const agreement = guardians.slice(0, 3).map((g) => bs582.decode(g).subarray(6));
1246
- assert(agreement.length === 3, "Not enough guardians to create agreement");
1247
- const keyring2 = await getKeyring();
1248
- const account = keyring2.getPairs()[0];
1249
- const { tx_result } = await signAndSend(tx, account, {
1250
- compute: { da_type: 1, agreement, verification: 0, compute: 1 }
1251
- });
1267
+ const guardians = contract.guardians;
1268
+ const agreement = guardians.map((g) => bs582.decode(g.peerid).subarray(6));
1269
+ const txContract = {
1270
+ ...contract,
1271
+ guardians: guardians.map((g) => g.address)
1272
+ };
1273
+ const tx = api2.tx.compute.agreement(txContract);
1274
+ const opts = {
1275
+ compute: {
1276
+ da_type: 1,
1277
+ agreement,
1278
+ verification: 0,
1279
+ compute: contract.contract_type === "Active" ? 1 : 0
1280
+ }
1281
+ };
1282
+ const { tx_result, blockNumber, index, hash } = await signAndSend(
1283
+ tx,
1284
+ account,
1285
+ opts
1286
+ );
1252
1287
  if (!tx_result.isError) {
1253
1288
  const agreementCreatedEvent = tx_result.events.find((event) => {
1254
1289
  return event.event.section === "compute" && event.event.method === "AgreementCreated";
@@ -1258,10 +1293,105 @@ async function createAgreement() {
1258
1293
  "Agreement data:",
1259
1294
  agreementCreatedEvent.event.data.toString()
1260
1295
  );
1296
+ return {
1297
+ blockNumber,
1298
+ index,
1299
+ hash,
1300
+ agreementId: agreementCreatedEvent.event.data[0]?.toHex?.() ?? agreementCreatedEvent.event.data.toString()
1301
+ };
1261
1302
  } else {
1262
1303
  debugLog("AgreementCreated event not found");
1263
1304
  }
1264
1305
  }
1306
+ return { blockNumber, index, hash };
1307
+ }
1308
+ async function createSimpleAgreement() {
1309
+ const guardianIds = (await getGuardianAddress()).slice(0, 3);
1310
+ assert(guardianIds.length === 3, "Not enough guardians to create agreement");
1311
+ const contract = {
1312
+ contract_type: "Dormant",
1313
+ guardians: guardianIds,
1314
+ pre_check: null,
1315
+ compute: {
1316
+ cipher: "Plaintext",
1317
+ computer_indices: [0, 1, 2],
1318
+ fees: 0n,
1319
+ deadline: 0,
1320
+ confidentiality: { Trusted: { trust_index: 0 } },
1321
+ fee_function: null,
1322
+ input: null,
1323
+ program: { NativeData: "DaFalse" },
1324
+ metadata: null
1325
+ },
1326
+ post_check: null,
1327
+ result_cipher: "Plaintext"
1328
+ };
1329
+ const keyring2 = await getKeyring();
1330
+ const account = keyring2.getPairs()[0];
1331
+ return createAgreement(contract, account);
1332
+ }
1333
+
1334
+ // src/compute/data.ts
1335
+ async function dataContract(params) {
1336
+ const keyring2 = await getKeyring();
1337
+ const account = keyring2.getPairs()[0];
1338
+ const plaintextCipher = "Plaintext";
1339
+ const atomicFees = toAtomicPaliAmount(params.fees ?? "0");
1340
+ const computeStep = {
1341
+ cipher: plaintextCipher,
1342
+ computer_indices: params.guardians.map((_, i) => i),
1343
+ fees: atomicFees,
1344
+ deadline: params.deadline ?? 0,
1345
+ confidentiality: {
1346
+ Trusted: {
1347
+ trust_index: params.trustIndex ?? 0
1348
+ }
1349
+ },
1350
+ fee_function: null,
1351
+ input: {
1352
+ Url: {
1353
+ url: Array.from(new TextEncoder().encode(params.url))
1354
+ }
1355
+ },
1356
+ program: {
1357
+ NativeData: "DaFalse"
1358
+ }
1359
+ };
1360
+ const contract = {
1361
+ contract_type: "Dormant",
1362
+ guardians: params.guardians,
1363
+ pre_check: null,
1364
+ compute: computeStep,
1365
+ post_check: null,
1366
+ result_cipher: plaintextCipher
1367
+ };
1368
+ return createAgreement(contract, account);
1369
+ }
1370
+
1371
+ // src/compute/inference.ts
1372
+ async function inferenceCompute(params) {
1373
+ const keyring2 = await getKeyring();
1374
+ const account = keyring2.getPairs()[0];
1375
+ const inputData = typeof params.input === "string" ? Array.from(new TextEncoder().encode(params.input)) : Array.from(params.input);
1376
+ const atomicFees = toAtomicPaliAmount(params.fees ?? "0");
1377
+ const plaintextCipher = "Plaintext";
1378
+ const computeStep = {
1379
+ cipher: plaintextCipher,
1380
+ computer_indices: params.guardians.map((_, i) => i),
1381
+ fees: atomicFees,
1382
+ deadline: params.deadline ?? 0,
1383
+ confidentiality: { Trusted: { trust_index: 0 } },
1384
+ fee_function: null,
1385
+ input: { Inline: { data: inputData } },
1386
+ program: { NativeExecute: "Inference" }
1387
+ };
1388
+ const contract = {
1389
+ contract_type: "Active",
1390
+ guardians: params.guardians,
1391
+ compute: computeStep,
1392
+ result_cipher: plaintextCipher
1393
+ };
1394
+ return createAgreement(contract, account);
1265
1395
  }
1266
1396
 
1267
1397
  // src/compute/participants.ts
@@ -1327,6 +1457,46 @@ async function getGuardianParticipants() {
1327
1457
  }
1328
1458
  }
1329
1459
 
1460
+ // src/compute/simple.ts
1461
+ async function simpleCompute(params) {
1462
+ const keyring2 = await getKeyring();
1463
+ const account = keyring2.getPairs()[0];
1464
+ const plaintextCipher = "Plaintext";
1465
+ const atomicFees = toAtomicPaliAmount(params.fees ?? "0");
1466
+ const computeStep = {
1467
+ cipher: plaintextCipher,
1468
+ computer_indices: params.guardians.map((_, i) => i),
1469
+ fees: atomicFees,
1470
+ deadline: params.deadline ?? 0,
1471
+ confidentiality: {
1472
+ Trusted: {
1473
+ trust_index: params.trustIndex ?? 0
1474
+ }
1475
+ },
1476
+ fee_function: null,
1477
+ input: {
1478
+ ChainTransaction: {
1479
+ block_number: params.inputBlockNumber,
1480
+ extrinsic_index: params.inputExtrinsicIndex
1481
+ }
1482
+ },
1483
+ program: {
1484
+ Url: {
1485
+ url: Array.from(new TextEncoder().encode(params.programUrl))
1486
+ }
1487
+ }
1488
+ };
1489
+ const contract = {
1490
+ contract_type: "Active",
1491
+ guardians: params.guardians,
1492
+ pre_check: null,
1493
+ compute: computeStep,
1494
+ post_check: null,
1495
+ result_cipher: plaintextCipher
1496
+ };
1497
+ return createAgreement(contract, account);
1498
+ }
1499
+
1330
1500
  // src/crypto/random.ts
1331
1501
  function generateRandomBytes(length = 32) {
1332
1502
  const bytes = new Uint8Array(length);
@@ -1349,6 +1519,7 @@ async function writeMetadata(account, name, description, ref, price, dataType, l
1349
1519
  const ownerBytes = Array.from(encoder.encode(l2Owner));
1350
1520
  const api2 = await getApi();
1351
1521
  assert(api2, "Failed to get API connection");
1522
+ debugLog(`Registering metadata for ${name} at ${formatPaliAmount(price)}`);
1352
1523
  const request = api2.tx.dataAvailability.daccRegisterData(
1353
1524
  nameBytes,
1354
1525
  descriptionBytes,
@@ -1362,6 +1533,82 @@ async function writeMetadata(account, name, description, ref, price, dataType, l
1362
1533
  debugLog(`Metadata registration transaction sent with hash: ${hash.hash}`);
1363
1534
  return hash;
1364
1535
  }
1536
+ async function registerDataAgreement(account, params) {
1537
+ debugLog(
1538
+ `Registering data agreement for DA ref ${params.ref.blockNumber}-${params.ref.index} at ${formatPaliAmount(params.fees)}`
1539
+ );
1540
+ const cipher = params.cipher ?? "Plaintext";
1541
+ const resultCipher = params.resultCipher ?? "Plaintext";
1542
+ const encoder = new TextEncoder();
1543
+ const computeMetadata = params.metadata ? {
1544
+ name: Array.from(encoder.encode(params.metadata.name)),
1545
+ description: Array.from(encoder.encode(params.metadata.description)),
1546
+ store_type: params.metadata.storeType,
1547
+ group_id: params.metadata.groupId
1548
+ } : null;
1549
+ const computeStep = {
1550
+ cipher,
1551
+ computer_indices: params.guardians.map((_, i) => i),
1552
+ fees: params.fees,
1553
+ deadline: params.deadline ?? 0,
1554
+ confidentiality: {
1555
+ Trusted: {
1556
+ trust_index: params.trustIndex ?? 0
1557
+ }
1558
+ },
1559
+ fee_function: null,
1560
+ input: {
1561
+ ChainTransaction: {
1562
+ block_number: params.ref.blockNumber,
1563
+ extrinsic_index: params.ref.index
1564
+ }
1565
+ },
1566
+ program: {
1567
+ NativeData: "DaFalse"
1568
+ },
1569
+ metadata: computeMetadata
1570
+ };
1571
+ const contract = {
1572
+ contract_type: "Dormant",
1573
+ guardians: params.guardians,
1574
+ pre_check: null,
1575
+ compute: computeStep,
1576
+ post_check: null,
1577
+ result_cipher: resultCipher
1578
+ };
1579
+ return createAgreement(contract, account);
1580
+ }
1581
+
1582
+ // src/da/runAgent.ts
1583
+ async function runAgent(account, agentRef, nonce, ciphertext, tdParams, pkBytes, tauParams, baseModel, publicKey, guardians, guardian, agreementId) {
1584
+ const agentRefTuple = [agentRef.blockNumber, agentRef.index];
1585
+ const baseModelTuple = [baseModel.blockNumber, baseModel.index];
1586
+ const api2 = await getApi();
1587
+ assert(api2, "Failed to get API connection");
1588
+ const request = api2.tx.dataAvailability.daccRunAgent(
1589
+ agentRefTuple,
1590
+ Array.from(nonce),
1591
+ Array.from(ciphertext),
1592
+ guardian ? Array.from(guardian) : null,
1593
+ Array.from(tdParams),
1594
+ Array.from(pkBytes),
1595
+ Array.from(tauParams),
1596
+ baseModelTuple,
1597
+ Array.from(publicKey),
1598
+ guardians.map((g) => Array.from(g))
1599
+ );
1600
+ const opts = {
1601
+ compute: {
1602
+ da_type: 4,
1603
+ verification: 0,
1604
+ compute: 1,
1605
+ agreement: [agreementId]
1606
+ }
1607
+ };
1608
+ const hash = await signAndSend(request, account, opts);
1609
+ debugLog(`Run agent transaction sent with hash: ${hash.hash}`);
1610
+ return hash;
1611
+ }
1365
1612
 
1366
1613
  // src/da/submit.ts
1367
1614
  async function submitData(account, data) {
@@ -1395,11 +1642,76 @@ async function submitTEData(account, data, chosenGuardians, tau_params, agg_key,
1395
1642
  debugLog(`TE data availability transaction sent with hash: ${hash.hash}`);
1396
1643
  return hash;
1397
1644
  }
1645
+ async function submitTEDataWithCipher(account, data, chosenGuardians, tau_params, agg_key, group_pk) {
1646
+ const { encoded: encryptedKey, ikm } = testCrypt(tau_params, agg_key);
1647
+ const shared_key = gen_stretched_key(hexToUint8Array(ikm));
1648
+ const encoder = new TextEncoder();
1649
+ const dataUint8Array = encoder.encode(data);
1650
+ const { ciphertext, nonce } = encrypt2(dataUint8Array, shared_key);
1651
+ const ciphertextHex = "0x" + Array.from(ciphertext).map((b) => b.toString(16).padStart(2, "0")).join("");
1652
+ const api2 = await getApi();
1653
+ assert(api2, "Failed to get API connection");
1654
+ const request = await api2.tx.dataAvailability.submitData(ciphertextHex);
1655
+ const ref = await signAndSend(request, account, DEFAULT_EMPTY_PAYLOAD);
1656
+ debugLog(`TE data availability transaction sent with hash: ${ref.hash}`);
1657
+ return {
1658
+ ref,
1659
+ cipher: {
1660
+ Encrypted: {
1661
+ threshold: {
1662
+ SilentThreshold: {
1663
+ td_params: Array.from(hexToUint8Array(encryptedKey)),
1664
+ pk_bytes: Array.from(hexToUint8Array(group_pk)),
1665
+ tau_params: Array.from(hexToUint8Array(tau_params))
1666
+ }
1667
+ },
1668
+ symmetric: {
1669
+ ChaCha20Poly1305: { nonce: Array.from(nonce) }
1670
+ }
1671
+ }
1672
+ }
1673
+ };
1674
+ }
1398
1675
 
1399
1676
  // src/da/upload.ts
1400
1677
  import fs from "fs";
1401
1678
  import path from "path";
1402
1679
  async function uploadData(options) {
1680
+ const { name, description, price, type, guardianGroupInfo, ref, filePath } = options;
1681
+ assert(
1682
+ guardianGroupInfo.guardians && guardianGroupInfo.tauParams && guardianGroupInfo.aggKey && guardianGroupInfo.groupPk,
1683
+ "Guardian group info is missing required properties"
1684
+ );
1685
+ console.log("Guardian group info:", guardianGroupInfo);
1686
+ const account = (await getKeyring()).pairs[0];
1687
+ const atomicPrice = toAtomicPaliAmount(price);
1688
+ if (filePath) {
1689
+ throw new Error("uploadData: file path upload is not implemented");
1690
+ } else {
1691
+ const storeType = type === "model" ? "Model" : type === "agent" ? "Agent" : "Dataset";
1692
+ const { ref: dataRef, cipher } = await submitTEDataWithCipher(
1693
+ account,
1694
+ ref || "",
1695
+ guardianGroupInfo.guardians,
1696
+ guardianGroupInfo.tauParams,
1697
+ guardianGroupInfo.aggKey,
1698
+ guardianGroupInfo.groupPk
1699
+ );
1700
+ await registerDataAgreement(account, {
1701
+ ref: dataRef,
1702
+ guardians: guardianGroupInfo.guardians,
1703
+ fees: atomicPrice,
1704
+ cipher,
1705
+ metadata: {
1706
+ name,
1707
+ description,
1708
+ storeType,
1709
+ groupId: guardianGroupInfo.groupId
1710
+ }
1711
+ });
1712
+ }
1713
+ }
1714
+ async function uploadDataLegacy(options) {
1403
1715
  const { name, description, price, type, guardianGroupInfo, ref, filePath } = options;
1404
1716
  assert(
1405
1717
  guardianGroupInfo.guardians && guardianGroupInfo.tauParams && guardianGroupInfo.aggKey && guardianGroupInfo.groupPk,
@@ -1407,6 +1719,7 @@ async function uploadData(options) {
1407
1719
  );
1408
1720
  const account = (await getKeyring()).pairs[0];
1409
1721
  const ethAddress = "";
1722
+ const atomicPrice = toAtomicPaliAmount(price);
1410
1723
  if (type === "dataset" && filePath) {
1411
1724
  const fileContent = fs.readFileSync(filePath);
1412
1725
  const selectedFile = new File([fileContent], path.basename(filePath), {
@@ -1419,7 +1732,7 @@ async function uploadData(options) {
1419
1732
  fileName: selectedFile.name,
1420
1733
  filePath: "",
1421
1734
  description,
1422
- baseCost: BigInt(Number(price) * 10 ** 18),
1735
+ baseCost: atomicPrice,
1423
1736
  ownerL2Address: ethAddress,
1424
1737
  guardianInfo: guardianGroupInfo
1425
1738
  },
@@ -1452,12 +1765,12 @@ async function uploadData(options) {
1452
1765
  }
1453
1766
 
1454
1767
  // src/stake/add.ts
1455
- async function addStake(account, amount) {
1768
+ async function addStake(account, amountBaseUnits) {
1456
1769
  const api2 = await getApi();
1457
1770
  assert(api2, "API not initialized");
1458
1771
  assert(account, "Account not initialized");
1459
- debugLog("Using account:", account.address);
1460
- const stakeTx = api2.tx.staking.bondExtra(amount);
1772
+ debugLog("Using account:", account.address, "adding:", formatPaliAmount(amountBaseUnits));
1773
+ const stakeTx = api2.tx.staking.bondExtra(amountBaseUnits);
1461
1774
  const hash = await signAndSend(stakeTx, account);
1462
1775
  debugLog(`Stake transaction sent with hash: ${hash.hash}`);
1463
1776
  }
@@ -1473,14 +1786,14 @@ async function joinIdleStaker(account) {
1473
1786
  }
1474
1787
 
1475
1788
  // src/stake/new.ts
1476
- async function newStake(account, amount, rewardDestination = "Staked") {
1789
+ async function newStake(account, amountBaseUnits, rewardDestination = "Staked") {
1477
1790
  const api2 = await getApi();
1478
1791
  assert(api2, "API not initialized");
1479
1792
  assert(account, "Account not initialized");
1480
1793
  debugLog(
1481
- `Staking amount: ${amount} for account: ${account.address} with reward destination: ${rewardDestination}`
1794
+ `Staking amount: ${formatPaliAmount(amountBaseUnits)} for account: ${account.address} with reward destination: ${rewardDestination}`
1482
1795
  );
1483
- const stakeTx = api2.tx.staking.bond(amount, rewardDestination);
1796
+ const stakeTx = api2.tx.staking.bond(amountBaseUnits, rewardDestination);
1484
1797
  const hash = await signAndSend(stakeTx, account);
1485
1798
  debugLog(`Stake transaction sent with hash: ${hash.hash}`);
1486
1799
  }
@@ -1502,12 +1815,12 @@ async function payoutStake(account, eras, address) {
1502
1815
  }
1503
1816
 
1504
1817
  // src/stake/reduce.ts
1505
- async function reduceStake(account, amount) {
1818
+ async function reduceStake(account, amountBaseUnits) {
1506
1819
  const api2 = await getApi();
1507
1820
  assert(api2, "API not initialized");
1508
1821
  assert(account, "Account not initialized");
1509
- debugLog("Using account:", account.address);
1510
- const unstakeTx = api2.tx.staking.unbond(amount);
1822
+ debugLog("Using account:", account.address, "reducing:", formatPaliAmount(amountBaseUnits));
1823
+ const unstakeTx = api2.tx.staking.unbond(amountBaseUnits);
1511
1824
  const hash = await signAndSend(unstakeTx, account);
1512
1825
  debugLog(`Unstake transaction sent with hash: ${hash.hash}`);
1513
1826
  }
@@ -1518,7 +1831,7 @@ async function removeStake(account) {
1518
1831
  assert(api2, "API not initialized");
1519
1832
  assert(account, "Account not initialized");
1520
1833
  const stakeAmount = (await api2.query.staking.ledger(account.address))?.toPrimitive();
1521
- debugLog("Removing entire stake amount:", stakeAmount?.active || 0n);
1834
+ debugLog("Removing entire stake amount:", formatPaliAmount(stakeAmount?.active || 0n));
1522
1835
  const unstakeTx = api2.tx.staking.unbond(stakeAmount?.active || 0n);
1523
1836
  const hash = await signAndSend(unstakeTx, account);
1524
1837
  debugLog(`Unstake transaction sent with hash: ${hash.hash}`);
@@ -1535,25 +1848,25 @@ async function withdrawStake(account) {
1535
1848
  }
1536
1849
 
1537
1850
  // src/token/fund.ts
1538
- async function fundAccount(account, amount, address) {
1851
+ async function fundAccount(account, amountBaseUnits, address) {
1539
1852
  const addr = address ? address : account.address;
1540
1853
  const keyring2 = await getKeyring();
1541
1854
  const api2 = await getApi();
1542
1855
  assert(api2, "API not initialized");
1543
1856
  debugLog(`
1544
- Funding account: ${addr} with amount: ${amount}`);
1545
- const tx = api2.tx.balances.transferKeepAlive(addr, amount);
1857
+ Funding account: ${addr} with amount: ${formatPaliAmount(amountBaseUnits)}`);
1858
+ const tx = api2.tx.balances.transferKeepAlive(addr, amountBaseUnits);
1546
1859
  const hash = await signAndSend(tx, keyring2.getPairs()[0]);
1547
1860
  debugLog(`Fund transaction sent with hash: ${hash.hash}`);
1548
1861
  }
1549
1862
 
1550
1863
  // src/token/transfer.ts
1551
- async function transfer(account, amount, address) {
1864
+ async function transfer(account, amountBaseUnits, address) {
1552
1865
  const api2 = await getApi();
1553
1866
  assert(api2, "API not initialized");
1554
1867
  debugLog(`
1555
- Transferring funds to account: ${address} with amount: ${amount}`);
1556
- const tx = api2.tx.balances.transferKeepAlive(address, amount);
1868
+ Transferring funds to account: ${address} with amount: ${formatPaliAmount(amountBaseUnits)}`);
1869
+ const tx = api2.tx.balances.transferKeepAlive(address, amountBaseUnits);
1557
1870
  const hash = await signAndSend(tx, account);
1558
1871
  debugLog(`Transfer transaction sent with hash: ${hash.hash}`);
1559
1872
  }
@@ -1622,9 +1935,10 @@ export {
1622
1935
  MCryptFs,
1623
1936
  MCryptFsReader,
1624
1937
  MCryptFsWriter,
1938
+ PALI_DECIMALS,
1939
+ PALI_SYMBOL,
1625
1940
  PALLIORA_RPC_URL,
1626
1941
  PALLIORA_WS,
1627
- RpcApi,
1628
1942
  TX_WAIT_FINALIZATION,
1629
1943
  WsProvider3 as WsProvider,
1630
1944
  addStake,
@@ -1634,6 +1948,8 @@ export {
1634
1948
  createAccount,
1635
1949
  createAgreement,
1636
1950
  createGuardianGroup,
1951
+ createSimpleAgreement,
1952
+ dataContract,
1637
1953
  debugLog,
1638
1954
  decodeAggregateKey,
1639
1955
  decodeField,
@@ -1644,6 +1960,8 @@ export {
1644
1960
  encrypt2 as encrypt,
1645
1961
  fetchTokenProperties,
1646
1962
  formatBalanceWithTokenProperties,
1963
+ formatPaliAmount,
1964
+ fromAtomicPaliAmount,
1647
1965
  fundAccount,
1648
1966
  gen_shared_key,
1649
1967
  gen_stretched_key,
@@ -1657,8 +1975,8 @@ export {
1657
1975
  getGuardianNwParams,
1658
1976
  getGuardianParticipants,
1659
1977
  getKeyring,
1660
- getRpcApi,
1661
1978
  hexToUint8Array,
1979
+ inferenceCompute,
1662
1980
  joinGuardian,
1663
1981
  joinIdleStaker,
1664
1982
  joinValidator,
@@ -1667,18 +1985,24 @@ export {
1667
1985
  payoutStake,
1668
1986
  provider,
1669
1987
  reduceStake,
1988
+ registerDataAgreement,
1670
1989
  removeStake,
1671
1990
  rotateAndSetKeys,
1991
+ runAgent,
1672
1992
  setIdentity,
1673
1993
  setWorker,
1674
1994
  signAndSend,
1995
+ simpleCompute,
1675
1996
  submitData,
1676
1997
  submitTEData,
1998
+ submitTEDataWithCipher,
1677
1999
  testCrypt,
2000
+ toAtomicPaliAmount,
1678
2001
  tokenToBigint,
1679
2002
  transfer,
1680
2003
  uint8ArrayToBase64,
1681
2004
  uploadData,
2005
+ uploadDataLegacy,
1682
2006
  utilCrypto,
1683
2007
  wasmCrypto,
1684
2008
  withdrawStake,