phantasma-sdk-ts 0.5.1 → 0.6.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/cjs/core/link/phantasmaLink.js +39 -10
- package/dist/cjs/core/tx/ContractArtifacts.js +106 -0
- package/dist/cjs/core/tx/ContractTxHelper.js +120 -0
- package/dist/cjs/core/tx/index.js +2 -0
- package/dist/cjs/core/utils/Hex.js +1 -1
- package/dist/esm/core/link/phantasmaLink.js +39 -10
- package/dist/esm/core/tx/ContractArtifacts.js +96 -0
- package/dist/esm/core/tx/ContractTxHelper.js +116 -0
- package/dist/esm/core/tx/index.js +2 -0
- package/dist/esm/core/utils/Hex.js +1 -1
- package/dist/types/core/link/phantasmaLink.d.ts +3 -0
- package/dist/types/core/link/phantasmaLink.d.ts.map +1 -1
- package/dist/types/core/tx/ContractArtifacts.d.ts +53 -0
- package/dist/types/core/tx/ContractArtifacts.d.ts.map +1 -0
- package/dist/types/core/tx/ContractTxHelper.d.ts +41 -0
- package/dist/types/core/tx/ContractTxHelper.d.ts.map +1 -0
- package/dist/types/core/tx/index.d.ts +2 -0
- package/dist/types/core/tx/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -10,6 +10,8 @@ class PhantasmaLink {
|
|
|
10
10
|
//Construct The Link
|
|
11
11
|
constructor(dappID, logging = true) {
|
|
12
12
|
this.lastSocketErrorMessage = null;
|
|
13
|
+
this.socketTransport = null;
|
|
14
|
+
this.socketOpen = false;
|
|
13
15
|
this.requestID = 0;
|
|
14
16
|
//Message Logging
|
|
15
17
|
this.onMessage = (msg) => {
|
|
@@ -36,6 +38,19 @@ class PhantasmaLink {
|
|
|
36
38
|
this.onLogin = function (succ) { }; //Does Nothing for Now
|
|
37
39
|
this.onError = function (message) { }; //Does Nothing for Now
|
|
38
40
|
}
|
|
41
|
+
// Preserve wallet-side failure details whenever the transport provides them.
|
|
42
|
+
describeFailure(result, fallback) {
|
|
43
|
+
if (typeof result === 'string' && result.length > 0) {
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
if (result && typeof result.error === 'string' && result.error.length > 0) {
|
|
47
|
+
return result.error;
|
|
48
|
+
}
|
|
49
|
+
if (result && typeof result.message === 'string' && result.message.length > 0) {
|
|
50
|
+
return result.message;
|
|
51
|
+
}
|
|
52
|
+
return fallback;
|
|
53
|
+
}
|
|
39
54
|
//Connect To Wallet
|
|
40
55
|
login(onLoginCallback, onErrorCallback, version = 4, platform = 'phantasma', providerHint = 'poltergeist') {
|
|
41
56
|
this.providerHint = providerHint;
|
|
@@ -363,12 +378,19 @@ class PhantasmaLink {
|
|
|
363
378
|
if (this.socket) {
|
|
364
379
|
this.socket.close();
|
|
365
380
|
}
|
|
381
|
+
const useInjectedSocket =
|
|
382
|
+
// @ts-ignore
|
|
383
|
+
!!window.PhantasmaLinkSocket && this.providerHint !== 'poltergeist';
|
|
384
|
+
this.socketTransport = useInjectedSocket ? 'injected' : 'websocket';
|
|
385
|
+
this.socketOpen = false;
|
|
386
|
+
this.onMessage(useInjectedSocket
|
|
387
|
+
? 'Using injected PhantasmaLinkSocket transport'
|
|
388
|
+
: `Using raw WebSocket transport: ${path}`);
|
|
366
389
|
//@ts-ignore
|
|
367
|
-
this.socket =
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
: new WebSocket(path);
|
|
390
|
+
this.socket = useInjectedSocket
|
|
391
|
+
? // @ts-ignore
|
|
392
|
+
new PhantasmaLinkSocket()
|
|
393
|
+
: new WebSocket(path);
|
|
372
394
|
this.requestCallback = null;
|
|
373
395
|
this.lastSocketErrorMessage = null;
|
|
374
396
|
this.token = null;
|
|
@@ -379,6 +401,7 @@ class PhantasmaLink {
|
|
|
379
401
|
let that = this;
|
|
380
402
|
//Once Socket Opened
|
|
381
403
|
this.socket.onopen = function (e) {
|
|
404
|
+
that.socketOpen = true;
|
|
382
405
|
that.onMessage('Connection established, authorizing dapp in wallet...');
|
|
383
406
|
if (isResume) {
|
|
384
407
|
that.fetchWallet(undefined, undefined);
|
|
@@ -405,7 +428,7 @@ class PhantasmaLink {
|
|
|
405
428
|
});
|
|
406
429
|
}
|
|
407
430
|
else {
|
|
408
|
-
that.onError('Authorization failed...');
|
|
431
|
+
that.onError(that.describeFailure(result, 'Authorization failed...'));
|
|
409
432
|
that.disconnect('Auth Failure');
|
|
410
433
|
}
|
|
411
434
|
});
|
|
@@ -428,8 +451,9 @@ class PhantasmaLink {
|
|
|
428
451
|
that.onError('Could not obtain account info... Make sure you have an account currently logged in');
|
|
429
452
|
that.disconnect(true);
|
|
430
453
|
break;
|
|
431
|
-
case 'A previouus request is still pending'
|
|
432
|
-
|
|
454
|
+
case 'A previouus request is still pending':
|
|
455
|
+
case 'A previous request is still pending':
|
|
456
|
+
that.onError(that.describeFailure(obj, 'You have a pending action in your wallet'));
|
|
433
457
|
break;
|
|
434
458
|
case 'user rejected':
|
|
435
459
|
that.onError('Transaction cancelled by user in ' + that.wallet);
|
|
@@ -455,6 +479,7 @@ class PhantasmaLink {
|
|
|
455
479
|
};
|
|
456
480
|
//Cleanup After Socket Closes
|
|
457
481
|
this.socket.onclose = function (event) {
|
|
482
|
+
that.socketOpen = false;
|
|
458
483
|
const reason = event.reason && event.reason.length > 0
|
|
459
484
|
? event.reason
|
|
460
485
|
: that.lastSocketErrorMessage || (event.wasClean ? 'Wallet connection closed' : 'Connection terminated unexpectedly');
|
|
@@ -505,8 +530,11 @@ class PhantasmaLink {
|
|
|
505
530
|
this.requestCallback = callback;
|
|
506
531
|
const socket = this.socket;
|
|
507
532
|
const openState = typeof WebSocket !== 'undefined' && typeof WebSocket.OPEN === 'number' ? WebSocket.OPEN : 1;
|
|
508
|
-
const
|
|
509
|
-
|
|
533
|
+
const hasSend = socket && typeof socket.send === 'function';
|
|
534
|
+
const hasReadyState = socket && typeof socket.readyState === 'number';
|
|
535
|
+
const isSocketOpen = hasSend &&
|
|
536
|
+
(hasReadyState ? socket.readyState === openState : this.socketOpen);
|
|
537
|
+
if (!socket || !hasSend || !isSocketOpen) {
|
|
510
538
|
this.handleSocketFailure('Wallet connection is closed. Please reconnect to your wallet.');
|
|
511
539
|
return;
|
|
512
540
|
}
|
|
@@ -540,6 +568,7 @@ class PhantasmaLink {
|
|
|
540
568
|
//Disconnect The Wallet Connection Socket
|
|
541
569
|
disconnect(triggered) {
|
|
542
570
|
this.onMessage('Disconnecting Phantasma Link: ' + triggered);
|
|
571
|
+
this.socketOpen = false;
|
|
543
572
|
if (this.socket)
|
|
544
573
|
this.socket.close();
|
|
545
574
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.buildContractArtifactBundle = exports.buildContractArtifactManifest = exports.coerceContractBytes = exports.normalizeContractName = void 0;
|
|
7
|
+
const sha256_js_1 = __importDefault(require("crypto-js/sha256.js"));
|
|
8
|
+
const enc_hex_js_1 = __importDefault(require("crypto-js/enc-hex.js"));
|
|
9
|
+
const index_js_1 = require("../utils/index.js");
|
|
10
|
+
function sha256Hex(bytes) {
|
|
11
|
+
return (0, sha256_js_1.default)(enc_hex_js_1.default.parse((0, index_js_1.bytesToHex)(bytes))).toString(enc_hex_js_1.default);
|
|
12
|
+
}
|
|
13
|
+
function buildFileEntry(path, bytes) {
|
|
14
|
+
const trimmedPath = path.trim();
|
|
15
|
+
if (!trimmedPath) {
|
|
16
|
+
throw new Error('artifact path cannot be empty');
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
path: trimmedPath,
|
|
20
|
+
size: bytes.length,
|
|
21
|
+
sha256: sha256Hex(bytes),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function normalizeContractName(contractName) {
|
|
25
|
+
const trimmed = contractName.trim();
|
|
26
|
+
if (!trimmed) {
|
|
27
|
+
throw new Error('contractName cannot be empty');
|
|
28
|
+
}
|
|
29
|
+
return trimmed;
|
|
30
|
+
}
|
|
31
|
+
exports.normalizeContractName = normalizeContractName;
|
|
32
|
+
function coerceContractBytes(input, label) {
|
|
33
|
+
if (input instanceof Uint8Array) {
|
|
34
|
+
if (input.length === 0) {
|
|
35
|
+
throw new Error(`${label} cannot be empty`);
|
|
36
|
+
}
|
|
37
|
+
// Copy mutable buffers so callers can keep reusing their original arrays safely.
|
|
38
|
+
return new Uint8Array(input);
|
|
39
|
+
}
|
|
40
|
+
if (typeof input === 'string') {
|
|
41
|
+
const trimmed = input.trim();
|
|
42
|
+
if (!trimmed) {
|
|
43
|
+
throw new Error(`${label} cannot be empty`);
|
|
44
|
+
}
|
|
45
|
+
const bytes = (0, index_js_1.hexToBytes)(trimmed);
|
|
46
|
+
if (bytes.length === 0) {
|
|
47
|
+
throw new Error(`${label} cannot be empty`);
|
|
48
|
+
}
|
|
49
|
+
return bytes;
|
|
50
|
+
}
|
|
51
|
+
throw new Error(`${label} must be Uint8Array or hex string`);
|
|
52
|
+
}
|
|
53
|
+
exports.coerceContractBytes = coerceContractBytes;
|
|
54
|
+
function buildContractArtifactManifest(params) {
|
|
55
|
+
// The manifest is the stable handoff contract between compiler, CLI, frontend, and runbooks.
|
|
56
|
+
const contractName = normalizeContractName(params.contractName);
|
|
57
|
+
const compilerName = params.compilerName.trim();
|
|
58
|
+
const compilerVersion = params.compilerVersion.trim();
|
|
59
|
+
if (!compilerName) {
|
|
60
|
+
throw new Error('compilerName cannot be empty');
|
|
61
|
+
}
|
|
62
|
+
if (!compilerVersion) {
|
|
63
|
+
throw new Error('compilerVersion cannot be empty');
|
|
64
|
+
}
|
|
65
|
+
const scriptBytes = coerceContractBytes(params.script, 'script');
|
|
66
|
+
const abiBytes = coerceContractBytes(params.abi, 'abi');
|
|
67
|
+
let debugEntry;
|
|
68
|
+
if (params.debugPath !== undefined || params.debug !== undefined) {
|
|
69
|
+
if (!params.debugPath || params.debug === undefined) {
|
|
70
|
+
throw new Error('debugPath and debug must be provided together');
|
|
71
|
+
}
|
|
72
|
+
debugEntry = buildFileEntry(params.debugPath, coerceContractBytes(params.debug, 'debug'));
|
|
73
|
+
}
|
|
74
|
+
const manifest = {
|
|
75
|
+
format: 'pha.contract.artifacts/v1',
|
|
76
|
+
contractName,
|
|
77
|
+
createdAtUtc: (params.createdAtUtc ?? new Date().toISOString()).trim(),
|
|
78
|
+
compiler: {
|
|
79
|
+
name: compilerName,
|
|
80
|
+
version: compilerVersion,
|
|
81
|
+
},
|
|
82
|
+
files: {
|
|
83
|
+
script: buildFileEntry(params.scriptPath, scriptBytes),
|
|
84
|
+
abi: buildFileEntry(params.abiPath, abiBytes),
|
|
85
|
+
...(debugEntry ? { debug: debugEntry } : {}),
|
|
86
|
+
},
|
|
87
|
+
...(params.sourceFile ? { sourceFile: params.sourceFile } : {}),
|
|
88
|
+
};
|
|
89
|
+
if (!manifest.createdAtUtc) {
|
|
90
|
+
throw new Error('createdAtUtc cannot be empty');
|
|
91
|
+
}
|
|
92
|
+
return manifest;
|
|
93
|
+
}
|
|
94
|
+
exports.buildContractArtifactManifest = buildContractArtifactManifest;
|
|
95
|
+
function buildContractArtifactBundle(params) {
|
|
96
|
+
// Keep bundle materialization small and explicit so higher layers can choose their own IO/layout policy.
|
|
97
|
+
const bundle = {
|
|
98
|
+
contractName: normalizeContractName(params.contractName),
|
|
99
|
+
script: coerceContractBytes(params.script, 'script'),
|
|
100
|
+
abi: coerceContractBytes(params.abi, 'abi'),
|
|
101
|
+
...(params.debug !== undefined ? { debug: coerceContractBytes(params.debug, 'debug') } : {}),
|
|
102
|
+
...(params.manifest ? { manifest: params.manifest } : {}),
|
|
103
|
+
};
|
|
104
|
+
return bundle;
|
|
105
|
+
}
|
|
106
|
+
exports.buildContractArtifactBundle = buildContractArtifactBundle;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContractTxHelper = void 0;
|
|
4
|
+
const ProofOfWork_js_1 = require("../link/interfaces/ProofOfWork.js");
|
|
5
|
+
const DomainSettings_js_1 = require("../types/DomainSettings.js");
|
|
6
|
+
const index_js_1 = require("../utils/index.js");
|
|
7
|
+
const index_js_2 = require("../vm/index.js");
|
|
8
|
+
const Transaction_js_1 = require("./Transaction.js");
|
|
9
|
+
const ContractArtifacts_js_1 = require("./ContractArtifacts.js");
|
|
10
|
+
class ContractTxHelper {
|
|
11
|
+
static buildDeployScript(params) {
|
|
12
|
+
return this.buildContractLifecycleScript('Runtime.DeployContract', params);
|
|
13
|
+
}
|
|
14
|
+
static buildUpgradeScript(params) {
|
|
15
|
+
return this.buildContractLifecycleScript('Runtime.UpgradeContract', params);
|
|
16
|
+
}
|
|
17
|
+
static buildDeployTransaction(params) {
|
|
18
|
+
return this.buildContractLifecycleTransaction(this.buildDeployScript(params), params);
|
|
19
|
+
}
|
|
20
|
+
static buildUpgradeTransaction(params) {
|
|
21
|
+
return this.buildContractLifecycleTransaction(this.buildUpgradeScript(params), params);
|
|
22
|
+
}
|
|
23
|
+
static buildDeployTransactionAndEncode(params) {
|
|
24
|
+
const tx = this.buildDeployTransaction(params);
|
|
25
|
+
this.signTransaction(tx, params.signer, params.proofOfWork);
|
|
26
|
+
return tx.ToStringEncoded(true).toUpperCase();
|
|
27
|
+
}
|
|
28
|
+
static buildUpgradeTransactionAndEncode(params) {
|
|
29
|
+
const tx = this.buildUpgradeTransaction(params);
|
|
30
|
+
this.signTransaction(tx, params.signer, params.proofOfWork);
|
|
31
|
+
return tx.ToStringEncoded(true).toUpperCase();
|
|
32
|
+
}
|
|
33
|
+
static buildDeployScriptFromBundle(bundle, from, gasPrice, gasLimit) {
|
|
34
|
+
return this.buildDeployScript({
|
|
35
|
+
from,
|
|
36
|
+
contractName: bundle.contractName,
|
|
37
|
+
script: bundle.script,
|
|
38
|
+
abi: bundle.abi,
|
|
39
|
+
gasPrice,
|
|
40
|
+
gasLimit,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
static buildUpgradeScriptFromBundle(bundle, from, gasPrice, gasLimit) {
|
|
44
|
+
return this.buildUpgradeScript({
|
|
45
|
+
from,
|
|
46
|
+
contractName: bundle.contractName,
|
|
47
|
+
script: bundle.script,
|
|
48
|
+
abi: bundle.abi,
|
|
49
|
+
gasPrice,
|
|
50
|
+
gasLimit,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
static encodePayloadText(text) {
|
|
54
|
+
return (0, index_js_1.bytesToHex)(new TextEncoder().encode(text));
|
|
55
|
+
}
|
|
56
|
+
static buildContractLifecycleScript(interopName, params) {
|
|
57
|
+
// Keep deploy/upgrade on the same legacy VM script path so CLI and wallet flows generate identical transactions.
|
|
58
|
+
const fromAddress = this.normalizeAddress(params.from);
|
|
59
|
+
const contractName = (0, ContractArtifacts_js_1.normalizeContractName)(params.contractName);
|
|
60
|
+
const scriptBytes = (0, ContractArtifacts_js_1.coerceContractBytes)(params.script, 'script');
|
|
61
|
+
const abiBytes = (0, ContractArtifacts_js_1.coerceContractBytes)(params.abi, 'abi');
|
|
62
|
+
const gasPrice = this.normalizeSmallInteger(params.gasPrice ?? this.DefaultGasPrice, 'gasPrice');
|
|
63
|
+
const gasLimit = this.normalizeSmallInteger(params.gasLimit ?? this.DefaultGasLimit, 'gasLimit');
|
|
64
|
+
const nullAddress = new index_js_2.ScriptBuilder().NullAddress;
|
|
65
|
+
return new index_js_2.ScriptBuilder()
|
|
66
|
+
.BeginScript()
|
|
67
|
+
.AllowGas(fromAddress, nullAddress, gasPrice, gasLimit)
|
|
68
|
+
.CallInterop(interopName, [fromAddress, contractName, scriptBytes, abiBytes])
|
|
69
|
+
.SpendGas(fromAddress)
|
|
70
|
+
.EndScript();
|
|
71
|
+
}
|
|
72
|
+
static buildContractLifecycleTransaction(scriptHex, params) {
|
|
73
|
+
// Transaction construction stays separate from signing so callers can inspect or override the unsigned tx first.
|
|
74
|
+
const nexus = params.nexus.trim();
|
|
75
|
+
const chain = (params.chain ?? DomainSettings_js_1.DomainSettings.RootChainName).trim();
|
|
76
|
+
if (!nexus) {
|
|
77
|
+
throw new Error('nexus cannot be empty');
|
|
78
|
+
}
|
|
79
|
+
if (!chain) {
|
|
80
|
+
throw new Error('chain cannot be empty');
|
|
81
|
+
}
|
|
82
|
+
const payloadHex = params.payloadHex?.trim() ?? '';
|
|
83
|
+
return new Transaction_js_1.Transaction(nexus, chain, scriptHex, params.expiration ?? new Date(Date.now() + 5 * 60 * 1000), payloadHex);
|
|
84
|
+
}
|
|
85
|
+
static signTransaction(tx, signer, proofOfWork = ProofOfWork_js_1.ProofOfWork.Minimal) {
|
|
86
|
+
// Mining/signing is the only mutation stage; everything above should remain deterministic and side-effect free.
|
|
87
|
+
if (proofOfWork > 0) {
|
|
88
|
+
tx.mineTransaction(proofOfWork);
|
|
89
|
+
}
|
|
90
|
+
if (typeof signer === 'string') {
|
|
91
|
+
const trimmedWif = signer.trim();
|
|
92
|
+
if (!trimmedWif) {
|
|
93
|
+
throw new Error('signer WIF cannot be empty');
|
|
94
|
+
}
|
|
95
|
+
tx.sign(trimmedWif);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
tx.signWithKeys(signer);
|
|
99
|
+
}
|
|
100
|
+
static normalizeAddress(address) {
|
|
101
|
+
if (typeof address === 'string') {
|
|
102
|
+
const trimmed = address.trim();
|
|
103
|
+
if (!trimmed) {
|
|
104
|
+
throw new Error('from cannot be empty');
|
|
105
|
+
}
|
|
106
|
+
return trimmed;
|
|
107
|
+
}
|
|
108
|
+
return address;
|
|
109
|
+
}
|
|
110
|
+
static normalizeSmallInteger(value, label) {
|
|
111
|
+
const numeric = typeof value === 'bigint' ? Number(value) : value;
|
|
112
|
+
if (!Number.isSafeInteger(numeric) || numeric <= 0) {
|
|
113
|
+
throw new Error(`${label} must be a positive safe integer`);
|
|
114
|
+
}
|
|
115
|
+
return numeric;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
exports.ContractTxHelper = ContractTxHelper;
|
|
119
|
+
ContractTxHelper.DefaultGasPrice = DomainSettings_js_1.DomainSettings.DefaultMinimumGasFee;
|
|
120
|
+
ContractTxHelper.DefaultGasLimit = 100000;
|
|
@@ -15,5 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./ExecutionState.js"), exports);
|
|
18
|
+
__exportStar(require("./ContractArtifacts.js"), exports);
|
|
19
|
+
__exportStar(require("./ContractTxHelper.js"), exports);
|
|
18
20
|
__exportStar(require("./Transaction.js"), exports);
|
|
19
21
|
__exportStar(require("./utils.js"), exports);
|
|
@@ -18,7 +18,7 @@ function bytesToHex(bytes) {
|
|
|
18
18
|
exports.bytesToHex = bytesToHex;
|
|
19
19
|
function hexToBytes(hex) {
|
|
20
20
|
const trimmed = hex.trim();
|
|
21
|
-
const normalized = trimmed.startsWith('0x') ? trimmed.slice(2) : trimmed;
|
|
21
|
+
const normalized = trimmed.startsWith('0x') || trimmed.startsWith('0X') ? trimmed.slice(2) : trimmed;
|
|
22
22
|
if (normalized.length === 0) {
|
|
23
23
|
return new Uint8Array();
|
|
24
24
|
}
|
|
@@ -7,6 +7,8 @@ export class PhantasmaLink {
|
|
|
7
7
|
//Construct The Link
|
|
8
8
|
constructor(dappID, logging = true) {
|
|
9
9
|
this.lastSocketErrorMessage = null;
|
|
10
|
+
this.socketTransport = null;
|
|
11
|
+
this.socketOpen = false;
|
|
10
12
|
this.requestID = 0;
|
|
11
13
|
//Message Logging
|
|
12
14
|
this.onMessage = (msg) => {
|
|
@@ -33,6 +35,19 @@ export class PhantasmaLink {
|
|
|
33
35
|
this.onLogin = function (succ) { }; //Does Nothing for Now
|
|
34
36
|
this.onError = function (message) { }; //Does Nothing for Now
|
|
35
37
|
}
|
|
38
|
+
// Preserve wallet-side failure details whenever the transport provides them.
|
|
39
|
+
describeFailure(result, fallback) {
|
|
40
|
+
if (typeof result === 'string' && result.length > 0) {
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
if (result && typeof result.error === 'string' && result.error.length > 0) {
|
|
44
|
+
return result.error;
|
|
45
|
+
}
|
|
46
|
+
if (result && typeof result.message === 'string' && result.message.length > 0) {
|
|
47
|
+
return result.message;
|
|
48
|
+
}
|
|
49
|
+
return fallback;
|
|
50
|
+
}
|
|
36
51
|
//Connect To Wallet
|
|
37
52
|
login(onLoginCallback, onErrorCallback, version = 4, platform = 'phantasma', providerHint = 'poltergeist') {
|
|
38
53
|
this.providerHint = providerHint;
|
|
@@ -360,12 +375,19 @@ export class PhantasmaLink {
|
|
|
360
375
|
if (this.socket) {
|
|
361
376
|
this.socket.close();
|
|
362
377
|
}
|
|
378
|
+
const useInjectedSocket =
|
|
379
|
+
// @ts-ignore
|
|
380
|
+
!!window.PhantasmaLinkSocket && this.providerHint !== 'poltergeist';
|
|
381
|
+
this.socketTransport = useInjectedSocket ? 'injected' : 'websocket';
|
|
382
|
+
this.socketOpen = false;
|
|
383
|
+
this.onMessage(useInjectedSocket
|
|
384
|
+
? 'Using injected PhantasmaLinkSocket transport'
|
|
385
|
+
: `Using raw WebSocket transport: ${path}`);
|
|
363
386
|
//@ts-ignore
|
|
364
|
-
this.socket =
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
: new WebSocket(path);
|
|
387
|
+
this.socket = useInjectedSocket
|
|
388
|
+
? // @ts-ignore
|
|
389
|
+
new PhantasmaLinkSocket()
|
|
390
|
+
: new WebSocket(path);
|
|
369
391
|
this.requestCallback = null;
|
|
370
392
|
this.lastSocketErrorMessage = null;
|
|
371
393
|
this.token = null;
|
|
@@ -376,6 +398,7 @@ export class PhantasmaLink {
|
|
|
376
398
|
let that = this;
|
|
377
399
|
//Once Socket Opened
|
|
378
400
|
this.socket.onopen = function (e) {
|
|
401
|
+
that.socketOpen = true;
|
|
379
402
|
that.onMessage('Connection established, authorizing dapp in wallet...');
|
|
380
403
|
if (isResume) {
|
|
381
404
|
that.fetchWallet(undefined, undefined);
|
|
@@ -402,7 +425,7 @@ export class PhantasmaLink {
|
|
|
402
425
|
});
|
|
403
426
|
}
|
|
404
427
|
else {
|
|
405
|
-
that.onError('Authorization failed...');
|
|
428
|
+
that.onError(that.describeFailure(result, 'Authorization failed...'));
|
|
406
429
|
that.disconnect('Auth Failure');
|
|
407
430
|
}
|
|
408
431
|
});
|
|
@@ -425,8 +448,9 @@ export class PhantasmaLink {
|
|
|
425
448
|
that.onError('Could not obtain account info... Make sure you have an account currently logged in');
|
|
426
449
|
that.disconnect(true);
|
|
427
450
|
break;
|
|
428
|
-
case 'A previouus request is still pending'
|
|
429
|
-
|
|
451
|
+
case 'A previouus request is still pending':
|
|
452
|
+
case 'A previous request is still pending':
|
|
453
|
+
that.onError(that.describeFailure(obj, 'You have a pending action in your wallet'));
|
|
430
454
|
break;
|
|
431
455
|
case 'user rejected':
|
|
432
456
|
that.onError('Transaction cancelled by user in ' + that.wallet);
|
|
@@ -452,6 +476,7 @@ export class PhantasmaLink {
|
|
|
452
476
|
};
|
|
453
477
|
//Cleanup After Socket Closes
|
|
454
478
|
this.socket.onclose = function (event) {
|
|
479
|
+
that.socketOpen = false;
|
|
455
480
|
const reason = event.reason && event.reason.length > 0
|
|
456
481
|
? event.reason
|
|
457
482
|
: that.lastSocketErrorMessage || (event.wasClean ? 'Wallet connection closed' : 'Connection terminated unexpectedly');
|
|
@@ -502,8 +527,11 @@ export class PhantasmaLink {
|
|
|
502
527
|
this.requestCallback = callback;
|
|
503
528
|
const socket = this.socket;
|
|
504
529
|
const openState = typeof WebSocket !== 'undefined' && typeof WebSocket.OPEN === 'number' ? WebSocket.OPEN : 1;
|
|
505
|
-
const
|
|
506
|
-
|
|
530
|
+
const hasSend = socket && typeof socket.send === 'function';
|
|
531
|
+
const hasReadyState = socket && typeof socket.readyState === 'number';
|
|
532
|
+
const isSocketOpen = hasSend &&
|
|
533
|
+
(hasReadyState ? socket.readyState === openState : this.socketOpen);
|
|
534
|
+
if (!socket || !hasSend || !isSocketOpen) {
|
|
507
535
|
this.handleSocketFailure('Wallet connection is closed. Please reconnect to your wallet.');
|
|
508
536
|
return;
|
|
509
537
|
}
|
|
@@ -537,6 +565,7 @@ export class PhantasmaLink {
|
|
|
537
565
|
//Disconnect The Wallet Connection Socket
|
|
538
566
|
disconnect(triggered) {
|
|
539
567
|
this.onMessage('Disconnecting Phantasma Link: ' + triggered);
|
|
568
|
+
this.socketOpen = false;
|
|
540
569
|
if (this.socket)
|
|
541
570
|
this.socket.close();
|
|
542
571
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import SHA256 from 'crypto-js/sha256.js';
|
|
2
|
+
import hexEncoding from 'crypto-js/enc-hex.js';
|
|
3
|
+
import { bytesToHex, hexToBytes } from '../utils/index.js';
|
|
4
|
+
function sha256Hex(bytes) {
|
|
5
|
+
return SHA256(hexEncoding.parse(bytesToHex(bytes))).toString(hexEncoding);
|
|
6
|
+
}
|
|
7
|
+
function buildFileEntry(path, bytes) {
|
|
8
|
+
const trimmedPath = path.trim();
|
|
9
|
+
if (!trimmedPath) {
|
|
10
|
+
throw new Error('artifact path cannot be empty');
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
path: trimmedPath,
|
|
14
|
+
size: bytes.length,
|
|
15
|
+
sha256: sha256Hex(bytes),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function normalizeContractName(contractName) {
|
|
19
|
+
const trimmed = contractName.trim();
|
|
20
|
+
if (!trimmed) {
|
|
21
|
+
throw new Error('contractName cannot be empty');
|
|
22
|
+
}
|
|
23
|
+
return trimmed;
|
|
24
|
+
}
|
|
25
|
+
export function coerceContractBytes(input, label) {
|
|
26
|
+
if (input instanceof Uint8Array) {
|
|
27
|
+
if (input.length === 0) {
|
|
28
|
+
throw new Error(`${label} cannot be empty`);
|
|
29
|
+
}
|
|
30
|
+
// Copy mutable buffers so callers can keep reusing their original arrays safely.
|
|
31
|
+
return new Uint8Array(input);
|
|
32
|
+
}
|
|
33
|
+
if (typeof input === 'string') {
|
|
34
|
+
const trimmed = input.trim();
|
|
35
|
+
if (!trimmed) {
|
|
36
|
+
throw new Error(`${label} cannot be empty`);
|
|
37
|
+
}
|
|
38
|
+
const bytes = hexToBytes(trimmed);
|
|
39
|
+
if (bytes.length === 0) {
|
|
40
|
+
throw new Error(`${label} cannot be empty`);
|
|
41
|
+
}
|
|
42
|
+
return bytes;
|
|
43
|
+
}
|
|
44
|
+
throw new Error(`${label} must be Uint8Array or hex string`);
|
|
45
|
+
}
|
|
46
|
+
export function buildContractArtifactManifest(params) {
|
|
47
|
+
// The manifest is the stable handoff contract between compiler, CLI, frontend, and runbooks.
|
|
48
|
+
const contractName = normalizeContractName(params.contractName);
|
|
49
|
+
const compilerName = params.compilerName.trim();
|
|
50
|
+
const compilerVersion = params.compilerVersion.trim();
|
|
51
|
+
if (!compilerName) {
|
|
52
|
+
throw new Error('compilerName cannot be empty');
|
|
53
|
+
}
|
|
54
|
+
if (!compilerVersion) {
|
|
55
|
+
throw new Error('compilerVersion cannot be empty');
|
|
56
|
+
}
|
|
57
|
+
const scriptBytes = coerceContractBytes(params.script, 'script');
|
|
58
|
+
const abiBytes = coerceContractBytes(params.abi, 'abi');
|
|
59
|
+
let debugEntry;
|
|
60
|
+
if (params.debugPath !== undefined || params.debug !== undefined) {
|
|
61
|
+
if (!params.debugPath || params.debug === undefined) {
|
|
62
|
+
throw new Error('debugPath and debug must be provided together');
|
|
63
|
+
}
|
|
64
|
+
debugEntry = buildFileEntry(params.debugPath, coerceContractBytes(params.debug, 'debug'));
|
|
65
|
+
}
|
|
66
|
+
const manifest = {
|
|
67
|
+
format: 'pha.contract.artifacts/v1',
|
|
68
|
+
contractName,
|
|
69
|
+
createdAtUtc: (params.createdAtUtc ?? new Date().toISOString()).trim(),
|
|
70
|
+
compiler: {
|
|
71
|
+
name: compilerName,
|
|
72
|
+
version: compilerVersion,
|
|
73
|
+
},
|
|
74
|
+
files: {
|
|
75
|
+
script: buildFileEntry(params.scriptPath, scriptBytes),
|
|
76
|
+
abi: buildFileEntry(params.abiPath, abiBytes),
|
|
77
|
+
...(debugEntry ? { debug: debugEntry } : {}),
|
|
78
|
+
},
|
|
79
|
+
...(params.sourceFile ? { sourceFile: params.sourceFile } : {}),
|
|
80
|
+
};
|
|
81
|
+
if (!manifest.createdAtUtc) {
|
|
82
|
+
throw new Error('createdAtUtc cannot be empty');
|
|
83
|
+
}
|
|
84
|
+
return manifest;
|
|
85
|
+
}
|
|
86
|
+
export function buildContractArtifactBundle(params) {
|
|
87
|
+
// Keep bundle materialization small and explicit so higher layers can choose their own IO/layout policy.
|
|
88
|
+
const bundle = {
|
|
89
|
+
contractName: normalizeContractName(params.contractName),
|
|
90
|
+
script: coerceContractBytes(params.script, 'script'),
|
|
91
|
+
abi: coerceContractBytes(params.abi, 'abi'),
|
|
92
|
+
...(params.debug !== undefined ? { debug: coerceContractBytes(params.debug, 'debug') } : {}),
|
|
93
|
+
...(params.manifest ? { manifest: params.manifest } : {}),
|
|
94
|
+
};
|
|
95
|
+
return bundle;
|
|
96
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { ProofOfWork } from '../link/interfaces/ProofOfWork.js';
|
|
2
|
+
import { DomainSettings } from '../types/DomainSettings.js';
|
|
3
|
+
import { bytesToHex } from '../utils/index.js';
|
|
4
|
+
import { ScriptBuilder } from '../vm/index.js';
|
|
5
|
+
import { Transaction } from './Transaction.js';
|
|
6
|
+
import { coerceContractBytes, normalizeContractName } from './ContractArtifacts.js';
|
|
7
|
+
export class ContractTxHelper {
|
|
8
|
+
static buildDeployScript(params) {
|
|
9
|
+
return this.buildContractLifecycleScript('Runtime.DeployContract', params);
|
|
10
|
+
}
|
|
11
|
+
static buildUpgradeScript(params) {
|
|
12
|
+
return this.buildContractLifecycleScript('Runtime.UpgradeContract', params);
|
|
13
|
+
}
|
|
14
|
+
static buildDeployTransaction(params) {
|
|
15
|
+
return this.buildContractLifecycleTransaction(this.buildDeployScript(params), params);
|
|
16
|
+
}
|
|
17
|
+
static buildUpgradeTransaction(params) {
|
|
18
|
+
return this.buildContractLifecycleTransaction(this.buildUpgradeScript(params), params);
|
|
19
|
+
}
|
|
20
|
+
static buildDeployTransactionAndEncode(params) {
|
|
21
|
+
const tx = this.buildDeployTransaction(params);
|
|
22
|
+
this.signTransaction(tx, params.signer, params.proofOfWork);
|
|
23
|
+
return tx.ToStringEncoded(true).toUpperCase();
|
|
24
|
+
}
|
|
25
|
+
static buildUpgradeTransactionAndEncode(params) {
|
|
26
|
+
const tx = this.buildUpgradeTransaction(params);
|
|
27
|
+
this.signTransaction(tx, params.signer, params.proofOfWork);
|
|
28
|
+
return tx.ToStringEncoded(true).toUpperCase();
|
|
29
|
+
}
|
|
30
|
+
static buildDeployScriptFromBundle(bundle, from, gasPrice, gasLimit) {
|
|
31
|
+
return this.buildDeployScript({
|
|
32
|
+
from,
|
|
33
|
+
contractName: bundle.contractName,
|
|
34
|
+
script: bundle.script,
|
|
35
|
+
abi: bundle.abi,
|
|
36
|
+
gasPrice,
|
|
37
|
+
gasLimit,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
static buildUpgradeScriptFromBundle(bundle, from, gasPrice, gasLimit) {
|
|
41
|
+
return this.buildUpgradeScript({
|
|
42
|
+
from,
|
|
43
|
+
contractName: bundle.contractName,
|
|
44
|
+
script: bundle.script,
|
|
45
|
+
abi: bundle.abi,
|
|
46
|
+
gasPrice,
|
|
47
|
+
gasLimit,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
static encodePayloadText(text) {
|
|
51
|
+
return bytesToHex(new TextEncoder().encode(text));
|
|
52
|
+
}
|
|
53
|
+
static buildContractLifecycleScript(interopName, params) {
|
|
54
|
+
// Keep deploy/upgrade on the same legacy VM script path so CLI and wallet flows generate identical transactions.
|
|
55
|
+
const fromAddress = this.normalizeAddress(params.from);
|
|
56
|
+
const contractName = normalizeContractName(params.contractName);
|
|
57
|
+
const scriptBytes = coerceContractBytes(params.script, 'script');
|
|
58
|
+
const abiBytes = coerceContractBytes(params.abi, 'abi');
|
|
59
|
+
const gasPrice = this.normalizeSmallInteger(params.gasPrice ?? this.DefaultGasPrice, 'gasPrice');
|
|
60
|
+
const gasLimit = this.normalizeSmallInteger(params.gasLimit ?? this.DefaultGasLimit, 'gasLimit');
|
|
61
|
+
const nullAddress = new ScriptBuilder().NullAddress;
|
|
62
|
+
return new ScriptBuilder()
|
|
63
|
+
.BeginScript()
|
|
64
|
+
.AllowGas(fromAddress, nullAddress, gasPrice, gasLimit)
|
|
65
|
+
.CallInterop(interopName, [fromAddress, contractName, scriptBytes, abiBytes])
|
|
66
|
+
.SpendGas(fromAddress)
|
|
67
|
+
.EndScript();
|
|
68
|
+
}
|
|
69
|
+
static buildContractLifecycleTransaction(scriptHex, params) {
|
|
70
|
+
// Transaction construction stays separate from signing so callers can inspect or override the unsigned tx first.
|
|
71
|
+
const nexus = params.nexus.trim();
|
|
72
|
+
const chain = (params.chain ?? DomainSettings.RootChainName).trim();
|
|
73
|
+
if (!nexus) {
|
|
74
|
+
throw new Error('nexus cannot be empty');
|
|
75
|
+
}
|
|
76
|
+
if (!chain) {
|
|
77
|
+
throw new Error('chain cannot be empty');
|
|
78
|
+
}
|
|
79
|
+
const payloadHex = params.payloadHex?.trim() ?? '';
|
|
80
|
+
return new Transaction(nexus, chain, scriptHex, params.expiration ?? new Date(Date.now() + 5 * 60 * 1000), payloadHex);
|
|
81
|
+
}
|
|
82
|
+
static signTransaction(tx, signer, proofOfWork = ProofOfWork.Minimal) {
|
|
83
|
+
// Mining/signing is the only mutation stage; everything above should remain deterministic and side-effect free.
|
|
84
|
+
if (proofOfWork > 0) {
|
|
85
|
+
tx.mineTransaction(proofOfWork);
|
|
86
|
+
}
|
|
87
|
+
if (typeof signer === 'string') {
|
|
88
|
+
const trimmedWif = signer.trim();
|
|
89
|
+
if (!trimmedWif) {
|
|
90
|
+
throw new Error('signer WIF cannot be empty');
|
|
91
|
+
}
|
|
92
|
+
tx.sign(trimmedWif);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
tx.signWithKeys(signer);
|
|
96
|
+
}
|
|
97
|
+
static normalizeAddress(address) {
|
|
98
|
+
if (typeof address === 'string') {
|
|
99
|
+
const trimmed = address.trim();
|
|
100
|
+
if (!trimmed) {
|
|
101
|
+
throw new Error('from cannot be empty');
|
|
102
|
+
}
|
|
103
|
+
return trimmed;
|
|
104
|
+
}
|
|
105
|
+
return address;
|
|
106
|
+
}
|
|
107
|
+
static normalizeSmallInteger(value, label) {
|
|
108
|
+
const numeric = typeof value === 'bigint' ? Number(value) : value;
|
|
109
|
+
if (!Number.isSafeInteger(numeric) || numeric <= 0) {
|
|
110
|
+
throw new Error(`${label} must be a positive safe integer`);
|
|
111
|
+
}
|
|
112
|
+
return numeric;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
ContractTxHelper.DefaultGasPrice = DomainSettings.DefaultMinimumGasFee;
|
|
116
|
+
ContractTxHelper.DefaultGasLimit = 100000;
|
|
@@ -14,7 +14,7 @@ export function bytesToHex(bytes) {
|
|
|
14
14
|
}
|
|
15
15
|
export function hexToBytes(hex) {
|
|
16
16
|
const trimmed = hex.trim();
|
|
17
|
-
const normalized = trimmed.startsWith('0x') ? trimmed.slice(2) : trimmed;
|
|
17
|
+
const normalized = trimmed.startsWith('0x') || trimmed.startsWith('0X') ? trimmed.slice(2) : trimmed;
|
|
18
18
|
if (normalized.length === 0) {
|
|
19
19
|
return new Uint8Array();
|
|
20
20
|
}
|
|
@@ -10,6 +10,8 @@ export declare class PhantasmaLink {
|
|
|
10
10
|
socket: any;
|
|
11
11
|
requestCallback: any;
|
|
12
12
|
private lastSocketErrorMessage;
|
|
13
|
+
socketTransport: 'websocket' | 'injected' | null;
|
|
14
|
+
socketOpen: boolean;
|
|
13
15
|
token: any;
|
|
14
16
|
requestID: number;
|
|
15
17
|
account: IAccount;
|
|
@@ -21,6 +23,7 @@ export declare class PhantasmaLink {
|
|
|
21
23
|
platform: string;
|
|
22
24
|
constructor(dappID: any, logging?: boolean);
|
|
23
25
|
onMessage: (msg: string) => void;
|
|
26
|
+
private describeFailure;
|
|
24
27
|
login(onLoginCallback: (success: boolean) => void, onErrorCallback: (message: string) => void, version?: number, platform?: string, providerHint?: string): void;
|
|
25
28
|
invokeScript(script: string, callback: (message: string) => void): void;
|
|
26
29
|
signTx(script: any, payload: string | null, callback: (arg0: string) => void, onErrorCallback: () => void, pow?: ProofOfWork, signature?: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"phantasmaLink.d.ts","sourceRoot":"","sources":["../../../../src/core/link/phantasmaLink.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"phantasmaLink.d.ts","sourceRoot":"","sources":["../../../../src/core/link/phantasmaLink.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type ContractBinaryInput = Uint8Array | string;
|
|
2
|
+
export interface ContractArtifactFileEntry {
|
|
3
|
+
path: string;
|
|
4
|
+
size: number;
|
|
5
|
+
sha256: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ContractArtifactManifest {
|
|
8
|
+
format: 'pha.contract.artifacts/v1';
|
|
9
|
+
contractName: string;
|
|
10
|
+
createdAtUtc: string;
|
|
11
|
+
compiler: {
|
|
12
|
+
name: string;
|
|
13
|
+
version: string;
|
|
14
|
+
};
|
|
15
|
+
sourceFile?: string;
|
|
16
|
+
files: {
|
|
17
|
+
script: ContractArtifactFileEntry;
|
|
18
|
+
abi: ContractArtifactFileEntry;
|
|
19
|
+
debug?: ContractArtifactFileEntry;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export interface ContractArtifactBundle {
|
|
23
|
+
contractName: string;
|
|
24
|
+
script: Uint8Array;
|
|
25
|
+
abi: Uint8Array;
|
|
26
|
+
debug?: Uint8Array;
|
|
27
|
+
manifest?: ContractArtifactManifest;
|
|
28
|
+
}
|
|
29
|
+
export interface BuildContractArtifactManifestParams {
|
|
30
|
+
contractName: string;
|
|
31
|
+
compilerName: string;
|
|
32
|
+
compilerVersion: string;
|
|
33
|
+
scriptPath: string;
|
|
34
|
+
script: ContractBinaryInput;
|
|
35
|
+
abiPath: string;
|
|
36
|
+
abi: ContractBinaryInput;
|
|
37
|
+
sourceFile?: string;
|
|
38
|
+
debugPath?: string;
|
|
39
|
+
debug?: ContractBinaryInput;
|
|
40
|
+
createdAtUtc?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface BuildContractArtifactBundleParams {
|
|
43
|
+
contractName: string;
|
|
44
|
+
script: ContractBinaryInput;
|
|
45
|
+
abi: ContractBinaryInput;
|
|
46
|
+
debug?: ContractBinaryInput;
|
|
47
|
+
manifest?: ContractArtifactManifest;
|
|
48
|
+
}
|
|
49
|
+
export declare function normalizeContractName(contractName: string): string;
|
|
50
|
+
export declare function coerceContractBytes(input: ContractBinaryInput, label: string): Uint8Array;
|
|
51
|
+
export declare function buildContractArtifactManifest(params: BuildContractArtifactManifestParams): ContractArtifactManifest;
|
|
52
|
+
export declare function buildContractArtifactBundle(params: BuildContractArtifactBundleParams): ContractArtifactBundle;
|
|
53
|
+
//# sourceMappingURL=ContractArtifacts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContractArtifacts.d.ts","sourceRoot":"","sources":["../../../../src/core/tx/ContractArtifacts.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,2BAA2B,CAAC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE;QACL,MAAM,EAAE,yBAAyB,CAAC;QAClC,GAAG,EAAE,yBAAyB,CAAC;QAC/B,KAAK,CAAC,EAAE,yBAAyB,CAAC;KACnC,CAAC;CACH;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,UAAU,CAAC;IAChB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,wBAAwB,CAAC;CACrC;AAED,MAAM,WAAW,mCAAmC;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,mBAAmB,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iCAAiC;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,GAAG,EAAE,mBAAmB,CAAC;IACzB,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,CAAC,EAAE,wBAAwB,CAAC;CACrC;AAmBD,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAOlE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAwBzF;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,mCAAmC,GAC1C,wBAAwB,CA6C1B;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,iCAAiC,GACxC,sBAAsB,CAWxB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Address } from '../types/Address.js';
|
|
2
|
+
import { PhantasmaKeys } from '../types/PhantasmaKeys.js';
|
|
3
|
+
import { Transaction } from './Transaction.js';
|
|
4
|
+
import { ContractArtifactBundle, ContractBinaryInput } from './ContractArtifacts.js';
|
|
5
|
+
export interface ContractScriptBuildParams {
|
|
6
|
+
from: string | Address;
|
|
7
|
+
contractName: string;
|
|
8
|
+
script: ContractBinaryInput;
|
|
9
|
+
abi: ContractBinaryInput;
|
|
10
|
+
gasPrice?: number | bigint;
|
|
11
|
+
gasLimit?: number | bigint;
|
|
12
|
+
}
|
|
13
|
+
export interface ContractTransactionBuildParams extends ContractScriptBuildParams {
|
|
14
|
+
nexus: string;
|
|
15
|
+
chain?: string;
|
|
16
|
+
expiration?: Date;
|
|
17
|
+
payloadHex?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ContractTransactionSignParams extends ContractTransactionBuildParams {
|
|
20
|
+
signer: string | PhantasmaKeys;
|
|
21
|
+
proofOfWork?: number;
|
|
22
|
+
}
|
|
23
|
+
export declare class ContractTxHelper {
|
|
24
|
+
static readonly DefaultGasPrice: number;
|
|
25
|
+
static readonly DefaultGasLimit = 100000;
|
|
26
|
+
static buildDeployScript(params: ContractScriptBuildParams): string;
|
|
27
|
+
static buildUpgradeScript(params: ContractScriptBuildParams): string;
|
|
28
|
+
static buildDeployTransaction(params: ContractTransactionBuildParams): Transaction;
|
|
29
|
+
static buildUpgradeTransaction(params: ContractTransactionBuildParams): Transaction;
|
|
30
|
+
static buildDeployTransactionAndEncode(params: ContractTransactionSignParams): string;
|
|
31
|
+
static buildUpgradeTransactionAndEncode(params: ContractTransactionSignParams): string;
|
|
32
|
+
static buildDeployScriptFromBundle(bundle: ContractArtifactBundle, from: string | Address, gasPrice?: number | bigint, gasLimit?: number | bigint): string;
|
|
33
|
+
static buildUpgradeScriptFromBundle(bundle: ContractArtifactBundle, from: string | Address, gasPrice?: number | bigint, gasLimit?: number | bigint): string;
|
|
34
|
+
static encodePayloadText(text: string): string;
|
|
35
|
+
private static buildContractLifecycleScript;
|
|
36
|
+
private static buildContractLifecycleTransaction;
|
|
37
|
+
private static signTransaction;
|
|
38
|
+
private static normalizeAddress;
|
|
39
|
+
private static normalizeSmallInteger;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=ContractTxHelper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContractTxHelper.d.ts","sourceRoot":"","sources":["../../../../src/core/tx/ContractTxHelper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAG1D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAA8C,MAAM,wBAAwB,CAAC;AAEjI,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,GAAG,EAAE,mBAAmB,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,8BAA+B,SAAQ,yBAAyB;IAC/E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,6BAA8B,SAAQ,8BAA8B;IACnF,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,gBAAgB;IAC3B,MAAM,CAAC,QAAQ,CAAC,eAAe,SAAuC;IACtE,MAAM,CAAC,QAAQ,CAAC,eAAe,UAAW;IAE1C,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM;IAInE,MAAM,CAAC,kBAAkB,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM;IAIpE,MAAM,CAAC,sBAAsB,CAAC,MAAM,EAAE,8BAA8B,GAAG,WAAW;IAIlF,MAAM,CAAC,uBAAuB,CAAC,MAAM,EAAE,8BAA8B,GAAG,WAAW;IAInF,MAAM,CAAC,+BAA+B,CAAC,MAAM,EAAE,6BAA6B,GAAG,MAAM;IAMrF,MAAM,CAAC,gCAAgC,CAAC,MAAM,EAAE,6BAA6B,GAAG,MAAM;IAMtF,MAAM,CAAC,2BAA2B,CAAC,MAAM,EAAE,sBAAsB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAW1J,MAAM,CAAC,4BAA4B,CAAC,MAAM,EAAE,sBAAsB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAW3J,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI9C,OAAO,CAAC,MAAM,CAAC,4BAA4B;IAqB3C,OAAO,CAAC,MAAM,CAAC,iCAAiC;IAyBhD,OAAO,CAAC,MAAM,CAAC,eAAe;IAsB9B,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAY/B,OAAO,CAAC,MAAM,CAAC,qBAAqB;CAQrC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/tx/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/tx/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
|