@imtbl/sdk 0.1.9-alpha.3 → 0.1.10-alpha
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/blockchain-data.d.ts +7 -5
- package/dist/blockchain-data.js +3 -3
- package/dist/browser/checkout.js +2 -2
- package/dist/immutablex_client.js +1 -1
- package/dist/index.cjs +467 -432
- package/dist/index.d.ts +7 -5
- package/dist/index.js +469 -434
- package/dist/passport.js +443 -408
- package/package.json +1 -1
package/dist/passport.js
CHANGED
|
@@ -21,7 +21,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
|
|
|
21
21
|
chainID,
|
|
22
22
|
coreContractAddress,
|
|
23
23
|
registrationContractAddress,
|
|
24
|
-
sdkVersion: 'ts-immutable-sdk-0.1.
|
|
24
|
+
sdkVersion: 'ts-immutable-sdk-0.1.10-alpha',
|
|
25
25
|
});
|
|
26
26
|
/**
|
|
27
27
|
* Sets `sdkVersion` at the time of build
|
|
@@ -524,69 +524,6 @@ class ImmutableXClient {
|
|
|
524
524
|
}
|
|
525
525
|
}
|
|
526
526
|
|
|
527
|
-
// used to sign message with L1 keys. Used for registration
|
|
528
|
-
function serializeEthSignature(sig) {
|
|
529
|
-
// This is because golang appends a recovery param
|
|
530
|
-
// https://github.com/ethers-io/ethers.js/issues/823
|
|
531
|
-
return encUtils.addHexPrefix(encUtils.padLeft(sig.r.toString(16), 64)
|
|
532
|
-
+ encUtils.padLeft(sig.s.toString(16), 64)
|
|
533
|
-
+ encUtils.padLeft(sig.recoveryParam?.toString(16) || '', 2));
|
|
534
|
-
}
|
|
535
|
-
function importRecoveryParam(v) {
|
|
536
|
-
const isValidBigNumber = new BN(v, 16).cmp(new BN(27)) !== -1
|
|
537
|
-
? new BN(v, 16).sub(new BN(27)).toNumber()
|
|
538
|
-
: new BN(v, 16).toNumber();
|
|
539
|
-
return v.trim()
|
|
540
|
-
? isValidBigNumber
|
|
541
|
-
: undefined;
|
|
542
|
-
}
|
|
543
|
-
// used chained with serializeEthSignature. serializeEthSignature(deserializeSignature(...))
|
|
544
|
-
function deserializeSignature(sig, size = 64) {
|
|
545
|
-
const removedHexPrefixSig = encUtils.removeHexPrefix(sig);
|
|
546
|
-
return {
|
|
547
|
-
r: new BN(removedHexPrefixSig.substring(0, size), 'hex'),
|
|
548
|
-
s: new BN(removedHexPrefixSig.substring(size, size * 2), 'hex'),
|
|
549
|
-
recoveryParam: importRecoveryParam(removedHexPrefixSig.substring(size * 2, size * 2 + 2)),
|
|
550
|
-
};
|
|
551
|
-
}
|
|
552
|
-
async function signRaw(payload, signer) {
|
|
553
|
-
const signature = deserializeSignature(await signer.signMessage(payload));
|
|
554
|
-
return serializeEthSignature(signature);
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* Helper method to convert token type to a SignableToken type
|
|
559
|
-
* @param token - the token type to convert to a SignableToken type
|
|
560
|
-
* @returns the converted SignableToken
|
|
561
|
-
*/
|
|
562
|
-
function convertToSignableToken(token) {
|
|
563
|
-
switch (token.type) {
|
|
564
|
-
case 'ERC721':
|
|
565
|
-
return {
|
|
566
|
-
type: 'ERC721',
|
|
567
|
-
data: {
|
|
568
|
-
token_id: token.tokenId,
|
|
569
|
-
token_address: token.tokenAddress,
|
|
570
|
-
},
|
|
571
|
-
};
|
|
572
|
-
case 'ERC20':
|
|
573
|
-
return {
|
|
574
|
-
type: 'ERC20',
|
|
575
|
-
data: {
|
|
576
|
-
token_address: token.tokenAddress,
|
|
577
|
-
},
|
|
578
|
-
};
|
|
579
|
-
case 'ETH':
|
|
580
|
-
default:
|
|
581
|
-
return {
|
|
582
|
-
type: 'ETH',
|
|
583
|
-
data: {
|
|
584
|
-
decimals: 18,
|
|
585
|
-
},
|
|
586
|
-
};
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
527
|
function bind(fn, thisArg) {
|
|
591
528
|
return function wrap() {
|
|
592
529
|
return fn.apply(thisArg, arguments);
|
|
@@ -3798,7 +3735,7 @@ var globalAxios = axios;
|
|
|
3798
3735
|
/* tslint:disable */
|
|
3799
3736
|
/* eslint-disable */
|
|
3800
3737
|
/**
|
|
3801
|
-
*
|
|
3738
|
+
* Guardian
|
|
3802
3739
|
* Guardian API
|
|
3803
3740
|
*
|
|
3804
3741
|
* The version of the OpenAPI document: 1.0.0
|
|
@@ -3808,7 +3745,7 @@ var globalAxios = axios;
|
|
|
3808
3745
|
* https://openapi-generator.tech
|
|
3809
3746
|
* Do not edit the class manually.
|
|
3810
3747
|
*/
|
|
3811
|
-
const BASE_PATH = "
|
|
3748
|
+
const BASE_PATH = "https://guardian.sandbox.imtbl.com".replace(/\/+$/, "");
|
|
3812
3749
|
/**
|
|
3813
3750
|
*
|
|
3814
3751
|
* @export
|
|
@@ -3845,7 +3782,7 @@ class RequiredError extends Error {
|
|
|
3845
3782
|
/* tslint:disable */
|
|
3846
3783
|
/* eslint-disable */
|
|
3847
3784
|
/**
|
|
3848
|
-
*
|
|
3785
|
+
* Guardian
|
|
3849
3786
|
* Guardian API
|
|
3850
3787
|
*
|
|
3851
3788
|
* The version of the OpenAPI document: 1.0.0
|
|
@@ -3911,6 +3848,19 @@ const setSearchParams = function (url, ...objects) {
|
|
|
3911
3848
|
setFlattenedQueryParams(searchParams, objects);
|
|
3912
3849
|
url.search = searchParams.toString();
|
|
3913
3850
|
};
|
|
3851
|
+
/**
|
|
3852
|
+
*
|
|
3853
|
+
* @export
|
|
3854
|
+
*/
|
|
3855
|
+
const serializeDataIfNeeded = function (value, requestOptions, configuration) {
|
|
3856
|
+
const nonString = typeof value !== 'string';
|
|
3857
|
+
const needsSerialization = nonString && configuration && configuration.isJsonMime
|
|
3858
|
+
? configuration.isJsonMime(requestOptions.headers['Content-Type'])
|
|
3859
|
+
: nonString;
|
|
3860
|
+
return needsSerialization
|
|
3861
|
+
? JSON.stringify(value !== undefined ? value : {})
|
|
3862
|
+
: (value || "");
|
|
3863
|
+
};
|
|
3914
3864
|
/**
|
|
3915
3865
|
*
|
|
3916
3866
|
* @export
|
|
@@ -3932,7 +3882,7 @@ const createRequestFunction = function (axiosArgs, globalAxios, BASE_PATH, confi
|
|
|
3932
3882
|
/* tslint:disable */
|
|
3933
3883
|
/* eslint-disable */
|
|
3934
3884
|
/**
|
|
3935
|
-
*
|
|
3885
|
+
* Guardian
|
|
3936
3886
|
* Guardian API
|
|
3937
3887
|
*
|
|
3938
3888
|
* The version of the OpenAPI document: 1.0.0
|
|
@@ -3943,22 +3893,25 @@ const createRequestFunction = function (axiosArgs, globalAxios, BASE_PATH, confi
|
|
|
3943
3893
|
* Do not edit the class manually.
|
|
3944
3894
|
*/
|
|
3945
3895
|
/**
|
|
3946
|
-
*
|
|
3896
|
+
* TransactionsApi - axios parameter creator
|
|
3947
3897
|
* @export
|
|
3948
3898
|
*/
|
|
3949
|
-
const
|
|
3899
|
+
const TransactionsApiAxiosParamCreator = function (configuration) {
|
|
3950
3900
|
return {
|
|
3951
3901
|
/**
|
|
3952
|
-
*
|
|
3953
|
-
* @summary
|
|
3902
|
+
* Approve a pending transaction
|
|
3903
|
+
* @summary Approve a pending transaction given chain
|
|
3954
3904
|
* @param {string} payloadHash Hash for the payload
|
|
3905
|
+
* @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transactio
|
|
3955
3906
|
* @param {*} [options] Override http request option.
|
|
3956
3907
|
* @throws {RequiredError}
|
|
3957
3908
|
*/
|
|
3958
|
-
|
|
3909
|
+
approvePendingTransaction: async (payloadHash, transactionApprovalRequest, options = {}) => {
|
|
3959
3910
|
// verify required parameter 'payloadHash' is not null or undefined
|
|
3960
|
-
assertParamExists('
|
|
3961
|
-
|
|
3911
|
+
assertParamExists('approvePendingTransaction', 'payloadHash', payloadHash);
|
|
3912
|
+
// verify required parameter 'transactionApprovalRequest' is not null or undefined
|
|
3913
|
+
assertParamExists('approvePendingTransaction', 'transactionApprovalRequest', transactionApprovalRequest);
|
|
3914
|
+
const localVarPath = `/guardian/v1/transactions/{payloadHash}/approve`
|
|
3962
3915
|
.replace(`{${"payloadHash"}}`, encodeURIComponent(String(payloadHash)));
|
|
3963
3916
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
|
3964
3917
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
|
@@ -3972,80 +3925,58 @@ const StarkexTransactionsApiAxiosParamCreator = function (configuration) {
|
|
|
3972
3925
|
// authentication BearerAuth required
|
|
3973
3926
|
// http bearer authentication required
|
|
3974
3927
|
await setBearerAuthToObject(localVarHeaderParameter, configuration);
|
|
3928
|
+
localVarHeaderParameter['Content-Type'] = 'application/json';
|
|
3975
3929
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
3976
3930
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
3977
3931
|
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
3932
|
+
localVarRequestOptions.data = serializeDataIfNeeded(transactionApprovalRequest, localVarRequestOptions, configuration);
|
|
3978
3933
|
return {
|
|
3979
3934
|
url: toPathString(localVarUrlObj),
|
|
3980
3935
|
options: localVarRequestOptions,
|
|
3981
3936
|
};
|
|
3982
3937
|
},
|
|
3983
|
-
};
|
|
3984
|
-
};
|
|
3985
|
-
/**
|
|
3986
|
-
* StarkexTransactionsApi - functional programming interface
|
|
3987
|
-
* @export
|
|
3988
|
-
*/
|
|
3989
|
-
const StarkexTransactionsApiFp = function (configuration) {
|
|
3990
|
-
const localVarAxiosParamCreator = StarkexTransactionsApiAxiosParamCreator(configuration);
|
|
3991
|
-
return {
|
|
3992
3938
|
/**
|
|
3993
|
-
* Check if
|
|
3994
|
-
* @summary Evaluate
|
|
3995
|
-
* @param {string} payloadHash
|
|
3939
|
+
* Check if the transaction is valid by transaction ID for both StarkEx and EVM
|
|
3940
|
+
* @summary Evaluate a transaction
|
|
3941
|
+
* @param {string} id Transaction identifier: payloadHash on StarkEx or EVM ID
|
|
3942
|
+
* @param {TransactionEvaluationRequest} transactionEvaluationRequest Specifies the kind of transaction
|
|
3996
3943
|
* @param {*} [options] Override http request option.
|
|
3997
3944
|
* @throws {RequiredError}
|
|
3998
3945
|
*/
|
|
3999
|
-
async
|
|
4000
|
-
|
|
4001
|
-
|
|
3946
|
+
evaluateTransaction: async (id, transactionEvaluationRequest, options = {}) => {
|
|
3947
|
+
// verify required parameter 'id' is not null or undefined
|
|
3948
|
+
assertParamExists('evaluateTransaction', 'id', id);
|
|
3949
|
+
// verify required parameter 'transactionEvaluationRequest' is not null or undefined
|
|
3950
|
+
assertParamExists('evaluateTransaction', 'transactionEvaluationRequest', transactionEvaluationRequest);
|
|
3951
|
+
const localVarPath = `/guardian/v1/transactions/{id}/evaluate`
|
|
3952
|
+
.replace(`{${"id"}}`, encodeURIComponent(String(id)));
|
|
3953
|
+
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
|
3954
|
+
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
|
3955
|
+
let baseOptions;
|
|
3956
|
+
if (configuration) {
|
|
3957
|
+
baseOptions = configuration.baseOptions;
|
|
3958
|
+
}
|
|
3959
|
+
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options };
|
|
3960
|
+
const localVarHeaderParameter = {};
|
|
3961
|
+
const localVarQueryParameter = {};
|
|
3962
|
+
// authentication BearerAuth required
|
|
3963
|
+
// http bearer authentication required
|
|
3964
|
+
await setBearerAuthToObject(localVarHeaderParameter, configuration);
|
|
3965
|
+
localVarHeaderParameter['Content-Type'] = 'application/json';
|
|
3966
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
3967
|
+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
3968
|
+
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
3969
|
+
localVarRequestOptions.data = serializeDataIfNeeded(transactionEvaluationRequest, localVarRequestOptions, configuration);
|
|
3970
|
+
return {
|
|
3971
|
+
url: toPathString(localVarUrlObj),
|
|
3972
|
+
options: localVarRequestOptions,
|
|
3973
|
+
};
|
|
4002
3974
|
},
|
|
4003
|
-
};
|
|
4004
|
-
};
|
|
4005
|
-
/**
|
|
4006
|
-
* StarkexTransactionsApi - object-oriented interface
|
|
4007
|
-
* @export
|
|
4008
|
-
* @class StarkexTransactionsApi
|
|
4009
|
-
* @extends {BaseAPI}
|
|
4010
|
-
*/
|
|
4011
|
-
class StarkexTransactionsApi extends BaseAPI {
|
|
4012
|
-
/**
|
|
4013
|
-
* Check if it is a valid transaction by payload hash
|
|
4014
|
-
* @summary Evaluate if it is an valid transaction
|
|
4015
|
-
* @param {StarkexTransactionsApiEvaluateStarkexTransactionRequest} requestParameters Request parameters.
|
|
4016
|
-
* @param {*} [options] Override http request option.
|
|
4017
|
-
* @throws {RequiredError}
|
|
4018
|
-
* @memberof StarkexTransactionsApi
|
|
4019
|
-
*/
|
|
4020
|
-
evaluateStarkexTransaction(requestParameters, options) {
|
|
4021
|
-
return StarkexTransactionsApiFp(this.configuration).evaluateStarkexTransaction(requestParameters.payloadHash, options).then((request) => request(this.axios, this.basePath));
|
|
4022
|
-
}
|
|
4023
|
-
}
|
|
4024
|
-
|
|
4025
|
-
/* tslint:disable */
|
|
4026
|
-
/* eslint-disable */
|
|
4027
|
-
/**
|
|
4028
|
-
* Swagger Guardian
|
|
4029
|
-
* Guardian API
|
|
4030
|
-
*
|
|
4031
|
-
* The version of the OpenAPI document: 1.0.0
|
|
4032
|
-
* Contact: support@immutable.com
|
|
4033
|
-
*
|
|
4034
|
-
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
4035
|
-
* https://openapi-generator.tech
|
|
4036
|
-
* Do not edit the class manually.
|
|
4037
|
-
*/
|
|
4038
|
-
/**
|
|
4039
|
-
* TransactionsApi - axios parameter creator
|
|
4040
|
-
* @export
|
|
4041
|
-
*/
|
|
4042
|
-
const TransactionsApiAxiosParamCreator = function (configuration) {
|
|
4043
|
-
return {
|
|
4044
3975
|
/**
|
|
4045
3976
|
* Get a transaction by payload hash
|
|
4046
3977
|
* @summary Info for a specific transaction
|
|
4047
3978
|
* @param {string} transactionID The id of the starkex transaction to retrieve
|
|
4048
|
-
* @param {
|
|
3979
|
+
* @param {'starkex' | 'evm'} chainType roll up type
|
|
4049
3980
|
* @param {number} [chainID] ID of evm chain
|
|
4050
3981
|
* @param {*} [options] Override http request option.
|
|
4051
3982
|
* @throws {RequiredError}
|
|
@@ -4092,11 +4023,35 @@ const TransactionsApiAxiosParamCreator = function (configuration) {
|
|
|
4092
4023
|
const TransactionsApiFp = function (configuration) {
|
|
4093
4024
|
const localVarAxiosParamCreator = TransactionsApiAxiosParamCreator(configuration);
|
|
4094
4025
|
return {
|
|
4026
|
+
/**
|
|
4027
|
+
* Approve a pending transaction
|
|
4028
|
+
* @summary Approve a pending transaction given chain
|
|
4029
|
+
* @param {string} payloadHash Hash for the payload
|
|
4030
|
+
* @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transactio
|
|
4031
|
+
* @param {*} [options] Override http request option.
|
|
4032
|
+
* @throws {RequiredError}
|
|
4033
|
+
*/
|
|
4034
|
+
async approvePendingTransaction(payloadHash, transactionApprovalRequest, options) {
|
|
4035
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.approvePendingTransaction(payloadHash, transactionApprovalRequest, options);
|
|
4036
|
+
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
|
4037
|
+
},
|
|
4038
|
+
/**
|
|
4039
|
+
* Check if the transaction is valid by transaction ID for both StarkEx and EVM
|
|
4040
|
+
* @summary Evaluate a transaction
|
|
4041
|
+
* @param {string} id Transaction identifier: payloadHash on StarkEx or EVM ID
|
|
4042
|
+
* @param {TransactionEvaluationRequest} transactionEvaluationRequest Specifies the kind of transaction
|
|
4043
|
+
* @param {*} [options] Override http request option.
|
|
4044
|
+
* @throws {RequiredError}
|
|
4045
|
+
*/
|
|
4046
|
+
async evaluateTransaction(id, transactionEvaluationRequest, options) {
|
|
4047
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.evaluateTransaction(id, transactionEvaluationRequest, options);
|
|
4048
|
+
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
|
4049
|
+
},
|
|
4095
4050
|
/**
|
|
4096
4051
|
* Get a transaction by payload hash
|
|
4097
4052
|
* @summary Info for a specific transaction
|
|
4098
4053
|
* @param {string} transactionID The id of the starkex transaction to retrieve
|
|
4099
|
-
* @param {
|
|
4054
|
+
* @param {'starkex' | 'evm'} chainType roll up type
|
|
4100
4055
|
* @param {number} [chainID] ID of evm chain
|
|
4101
4056
|
* @param {*} [options] Override http request option.
|
|
4102
4057
|
* @throws {RequiredError}
|
|
@@ -4114,6 +4069,28 @@ const TransactionsApiFp = function (configuration) {
|
|
|
4114
4069
|
* @extends {BaseAPI}
|
|
4115
4070
|
*/
|
|
4116
4071
|
class TransactionsApi extends BaseAPI {
|
|
4072
|
+
/**
|
|
4073
|
+
* Approve a pending transaction
|
|
4074
|
+
* @summary Approve a pending transaction given chain
|
|
4075
|
+
* @param {TransactionsApiApprovePendingTransactionRequest} requestParameters Request parameters.
|
|
4076
|
+
* @param {*} [options] Override http request option.
|
|
4077
|
+
* @throws {RequiredError}
|
|
4078
|
+
* @memberof TransactionsApi
|
|
4079
|
+
*/
|
|
4080
|
+
approvePendingTransaction(requestParameters, options) {
|
|
4081
|
+
return TransactionsApiFp(this.configuration).approvePendingTransaction(requestParameters.payloadHash, requestParameters.transactionApprovalRequest, options).then((request) => request(this.axios, this.basePath));
|
|
4082
|
+
}
|
|
4083
|
+
/**
|
|
4084
|
+
* Check if the transaction is valid by transaction ID for both StarkEx and EVM
|
|
4085
|
+
* @summary Evaluate a transaction
|
|
4086
|
+
* @param {TransactionsApiEvaluateTransactionRequest} requestParameters Request parameters.
|
|
4087
|
+
* @param {*} [options] Override http request option.
|
|
4088
|
+
* @throws {RequiredError}
|
|
4089
|
+
* @memberof TransactionsApi
|
|
4090
|
+
*/
|
|
4091
|
+
evaluateTransaction(requestParameters, options) {
|
|
4092
|
+
return TransactionsApiFp(this.configuration).evaluateTransaction(requestParameters.id, requestParameters.transactionEvaluationRequest, options).then((request) => request(this.axios, this.basePath));
|
|
4093
|
+
}
|
|
4117
4094
|
/**
|
|
4118
4095
|
* Get a transaction by payload hash
|
|
4119
4096
|
* @summary Info for a specific transaction
|
|
@@ -4130,7 +4107,7 @@ class TransactionsApi extends BaseAPI {
|
|
|
4130
4107
|
/* tslint:disable */
|
|
4131
4108
|
/* eslint-disable */
|
|
4132
4109
|
/**
|
|
4133
|
-
*
|
|
4110
|
+
* Guardian
|
|
4134
4111
|
* Guardian API
|
|
4135
4112
|
*
|
|
4136
4113
|
* The version of the OpenAPI document: 1.0.0
|
|
@@ -4215,6 +4192,69 @@ class Configuration {
|
|
|
4215
4192
|
}
|
|
4216
4193
|
}
|
|
4217
4194
|
|
|
4195
|
+
// used to sign message with L1 keys. Used for registration
|
|
4196
|
+
function serializeEthSignature(sig) {
|
|
4197
|
+
// This is because golang appends a recovery param
|
|
4198
|
+
// https://github.com/ethers-io/ethers.js/issues/823
|
|
4199
|
+
return encUtils.addHexPrefix(encUtils.padLeft(sig.r.toString(16), 64)
|
|
4200
|
+
+ encUtils.padLeft(sig.s.toString(16), 64)
|
|
4201
|
+
+ encUtils.padLeft(sig.recoveryParam?.toString(16) || '', 2));
|
|
4202
|
+
}
|
|
4203
|
+
function importRecoveryParam(v) {
|
|
4204
|
+
const isValidBigNumber = new BN(v, 16).cmp(new BN(27)) !== -1
|
|
4205
|
+
? new BN(v, 16).sub(new BN(27)).toNumber()
|
|
4206
|
+
: new BN(v, 16).toNumber();
|
|
4207
|
+
return v.trim()
|
|
4208
|
+
? isValidBigNumber
|
|
4209
|
+
: undefined;
|
|
4210
|
+
}
|
|
4211
|
+
// used chained with serializeEthSignature. serializeEthSignature(deserializeSignature(...))
|
|
4212
|
+
function deserializeSignature(sig, size = 64) {
|
|
4213
|
+
const removedHexPrefixSig = encUtils.removeHexPrefix(sig);
|
|
4214
|
+
return {
|
|
4215
|
+
r: new BN(removedHexPrefixSig.substring(0, size), 'hex'),
|
|
4216
|
+
s: new BN(removedHexPrefixSig.substring(size, size * 2), 'hex'),
|
|
4217
|
+
recoveryParam: importRecoveryParam(removedHexPrefixSig.substring(size * 2, size * 2 + 2)),
|
|
4218
|
+
};
|
|
4219
|
+
}
|
|
4220
|
+
async function signRaw(payload, signer) {
|
|
4221
|
+
const signature = deserializeSignature(await signer.signMessage(payload));
|
|
4222
|
+
return serializeEthSignature(signature);
|
|
4223
|
+
}
|
|
4224
|
+
|
|
4225
|
+
/**
|
|
4226
|
+
* Helper method to convert token type to a SignableToken type
|
|
4227
|
+
* @param token - the token type to convert to a SignableToken type
|
|
4228
|
+
* @returns the converted SignableToken
|
|
4229
|
+
*/
|
|
4230
|
+
function convertToSignableToken(token) {
|
|
4231
|
+
switch (token.type) {
|
|
4232
|
+
case 'ERC721':
|
|
4233
|
+
return {
|
|
4234
|
+
type: 'ERC721',
|
|
4235
|
+
data: {
|
|
4236
|
+
token_id: token.tokenId,
|
|
4237
|
+
token_address: token.tokenAddress,
|
|
4238
|
+
},
|
|
4239
|
+
};
|
|
4240
|
+
case 'ERC20':
|
|
4241
|
+
return {
|
|
4242
|
+
type: 'ERC20',
|
|
4243
|
+
data: {
|
|
4244
|
+
token_address: token.tokenAddress,
|
|
4245
|
+
},
|
|
4246
|
+
};
|
|
4247
|
+
case 'ETH':
|
|
4248
|
+
default:
|
|
4249
|
+
return {
|
|
4250
|
+
type: 'ETH',
|
|
4251
|
+
data: {
|
|
4252
|
+
decimals: 18,
|
|
4253
|
+
},
|
|
4254
|
+
};
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
4257
|
+
|
|
4218
4258
|
var PassportErrorType;
|
|
4219
4259
|
(function (PassportErrorType) {
|
|
4220
4260
|
PassportErrorType["AUTHENTICATION_ERROR"] = "AUTHENTICATION_ERROR";
|
|
@@ -4373,6 +4413,73 @@ const getStarkSigner = async (signer) => withPassportError(async () => {
|
|
|
4373
4413
|
return createStarkSigner(privateKey);
|
|
4374
4414
|
}, PassportErrorType.WALLET_CONNECTION_ERROR);
|
|
4375
4415
|
|
|
4416
|
+
const POLL_INTERVAL = 1 * 1000; // every 1 second
|
|
4417
|
+
const MAX_RETRIES = 3;
|
|
4418
|
+
const wait = (ms) => new Promise((resolve) => {
|
|
4419
|
+
setTimeout(() => resolve(), ms);
|
|
4420
|
+
});
|
|
4421
|
+
const retryWithDelay = async (fn, options) => {
|
|
4422
|
+
const { retries = MAX_RETRIES, interval = POLL_INTERVAL, finalErr = Error('Retry failed'), finallyFn = () => { }, } = options || {};
|
|
4423
|
+
try {
|
|
4424
|
+
return await fn();
|
|
4425
|
+
}
|
|
4426
|
+
catch (err) {
|
|
4427
|
+
if (retries <= 0) {
|
|
4428
|
+
return Promise.reject(finalErr);
|
|
4429
|
+
}
|
|
4430
|
+
await wait(interval);
|
|
4431
|
+
return retryWithDelay(fn, { retries: retries - 1, finalErr, finallyFn });
|
|
4432
|
+
}
|
|
4433
|
+
finally {
|
|
4434
|
+
if (retries <= 0) {
|
|
4435
|
+
finallyFn();
|
|
4436
|
+
}
|
|
4437
|
+
}
|
|
4438
|
+
};
|
|
4439
|
+
|
|
4440
|
+
class GuardianClient {
|
|
4441
|
+
transactionAPI;
|
|
4442
|
+
confirmationScreen;
|
|
4443
|
+
imxEtherAddress;
|
|
4444
|
+
constructor({ imxPublicApiDomain, accessToken, confirmationScreen, imxEtherAddress, }) {
|
|
4445
|
+
this.confirmationScreen = confirmationScreen;
|
|
4446
|
+
this.transactionAPI = new TransactionsApi(new Configuration({
|
|
4447
|
+
accessToken,
|
|
4448
|
+
basePath: imxPublicApiDomain,
|
|
4449
|
+
}));
|
|
4450
|
+
this.imxEtherAddress = imxEtherAddress;
|
|
4451
|
+
}
|
|
4452
|
+
async validate({ popupWindowSize, payloadHash }) {
|
|
4453
|
+
this.confirmationScreen.loading(popupWindowSize);
|
|
4454
|
+
const finallyFn = () => {
|
|
4455
|
+
this.confirmationScreen.closeWindow();
|
|
4456
|
+
};
|
|
4457
|
+
const transactionRes = await retryWithDelay(async () => this.transactionAPI.getTransactionByID({
|
|
4458
|
+
transactionID: payloadHash,
|
|
4459
|
+
chainType: 'starkex',
|
|
4460
|
+
}), { finallyFn });
|
|
4461
|
+
if (!transactionRes.data.id) {
|
|
4462
|
+
throw new Error("Transaction doesn't exists");
|
|
4463
|
+
}
|
|
4464
|
+
const evaluateStarkexRes = await this.transactionAPI.evaluateTransaction({
|
|
4465
|
+
id: payloadHash,
|
|
4466
|
+
transactionEvaluationRequest: {
|
|
4467
|
+
chainType: 'starkex',
|
|
4468
|
+
},
|
|
4469
|
+
});
|
|
4470
|
+
const { confirmationRequired } = evaluateStarkexRes.data;
|
|
4471
|
+
if (confirmationRequired) {
|
|
4472
|
+
const confirmationResult = await this.confirmationScreen.startGuardianTransaction(payloadHash, this.imxEtherAddress);
|
|
4473
|
+
if (!confirmationResult.confirmed) {
|
|
4474
|
+
throw new Error('Transaction rejected by user');
|
|
4475
|
+
}
|
|
4476
|
+
}
|
|
4477
|
+
else {
|
|
4478
|
+
this.confirmationScreen.closeWindow();
|
|
4479
|
+
}
|
|
4480
|
+
}
|
|
4481
|
+
}
|
|
4482
|
+
|
|
4376
4483
|
async function exchangeTransfer({ user, starkSigner, request, exchangesApi, }) {
|
|
4377
4484
|
return withPassportError(async () => {
|
|
4378
4485
|
const { ethAddress } = user.imx;
|
|
@@ -4417,165 +4524,16 @@ async function exchangeTransfer({ user, starkSigner, request, exchangesApi, }) {
|
|
|
4417
4524
|
}, PassportErrorType.EXCHANGE_TRANSFER_ERROR);
|
|
4418
4525
|
}
|
|
4419
4526
|
|
|
4420
|
-
var ReceiveMessage;
|
|
4421
|
-
(function (ReceiveMessage) {
|
|
4422
|
-
ReceiveMessage["CONFIRMATION_WINDOW_READY"] = "confirmation_window_ready";
|
|
4423
|
-
ReceiveMessage["TRANSACTION_CONFIRMED"] = "transaction_confirmed";
|
|
4424
|
-
ReceiveMessage["TRANSACTION_ERROR"] = "transaction_error";
|
|
4425
|
-
})(ReceiveMessage || (ReceiveMessage = {}));
|
|
4426
|
-
var SendMessage;
|
|
4427
|
-
(function (SendMessage) {
|
|
4428
|
-
SendMessage["TRANSACTION_START"] = "transaction_start";
|
|
4429
|
-
})(SendMessage || (SendMessage = {}));
|
|
4430
|
-
var TransactionTypes;
|
|
4431
|
-
(function (TransactionTypes) {
|
|
4432
|
-
TransactionTypes["cancelOrder"] = "delete:v1/orders";
|
|
4433
|
-
TransactionTypes["createOrder"] = "post:v1/orders";
|
|
4434
|
-
TransactionTypes["createTrade"] = "post:v1/trades";
|
|
4435
|
-
TransactionTypes["createTransfer"] = "post:v1/transfers";
|
|
4436
|
-
TransactionTypes["createBatchTransfer"] = "post:v2/transfers";
|
|
4437
|
-
})(TransactionTypes || (TransactionTypes = {}));
|
|
4438
|
-
const PASSPORT_EVENT_TYPE = 'imx_passport_confirmation';
|
|
4439
|
-
|
|
4440
|
-
const openPopupCenter = ({ url, title, width, height, }) => {
|
|
4441
|
-
const left = Math.max(0, Math.round(window.screenX + (window.outerWidth - width) / 2));
|
|
4442
|
-
const top = Math.max(0, Math.round(window.screenY + (window.outerHeight - height) / 2));
|
|
4443
|
-
const newWindow = window.open(url, title, `
|
|
4444
|
-
scrollbars=yes,
|
|
4445
|
-
width=${width},
|
|
4446
|
-
height=${height},
|
|
4447
|
-
top=${top},
|
|
4448
|
-
left=${left}
|
|
4449
|
-
`);
|
|
4450
|
-
if (!newWindow) {
|
|
4451
|
-
throw new Error('Failed to open confirmation screen');
|
|
4452
|
-
}
|
|
4453
|
-
newWindow.focus();
|
|
4454
|
-
return newWindow;
|
|
4455
|
-
};
|
|
4456
|
-
|
|
4457
|
-
const CONFIRMATION_WINDOW_TITLE = 'Confirm this transaction';
|
|
4458
|
-
const CONFIRMATION_WINDOW_HEIGHT = 380;
|
|
4459
|
-
const CONFIRMATION_WINDOW_WIDTH = 480;
|
|
4460
|
-
const CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION = 1000;
|
|
4461
|
-
class ConfirmationScreen {
|
|
4462
|
-
config;
|
|
4463
|
-
confirmationWindow;
|
|
4464
|
-
constructor(config) {
|
|
4465
|
-
this.config = config;
|
|
4466
|
-
}
|
|
4467
|
-
postMessage(destinationWindow, accessToken, message) {
|
|
4468
|
-
destinationWindow.postMessage({
|
|
4469
|
-
eventType: PASSPORT_EVENT_TYPE,
|
|
4470
|
-
accessToken,
|
|
4471
|
-
...message,
|
|
4472
|
-
}, this.config.passportDomain);
|
|
4473
|
-
}
|
|
4474
|
-
startTransaction(accessToken, transaction, popupOptions) {
|
|
4475
|
-
return new Promise((resolve, reject) => {
|
|
4476
|
-
const messageHandler = ({ data, origin }) => {
|
|
4477
|
-
if (origin !== this.config.passportDomain
|
|
4478
|
-
|| data.eventType !== PASSPORT_EVENT_TYPE) {
|
|
4479
|
-
return;
|
|
4480
|
-
}
|
|
4481
|
-
switch (data.messageType) {
|
|
4482
|
-
case ReceiveMessage.CONFIRMATION_WINDOW_READY: {
|
|
4483
|
-
// TODO: remove once fixed
|
|
4484
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
4485
|
-
this.postMessage(confirmationWindow, accessToken, {
|
|
4486
|
-
messageType: SendMessage.TRANSACTION_START,
|
|
4487
|
-
messageData: transaction,
|
|
4488
|
-
});
|
|
4489
|
-
break;
|
|
4490
|
-
}
|
|
4491
|
-
case ReceiveMessage.TRANSACTION_CONFIRMED: {
|
|
4492
|
-
resolve({ confirmed: true });
|
|
4493
|
-
break;
|
|
4494
|
-
}
|
|
4495
|
-
case ReceiveMessage.TRANSACTION_ERROR: {
|
|
4496
|
-
reject(new Error('Transaction error'));
|
|
4497
|
-
break;
|
|
4498
|
-
}
|
|
4499
|
-
default:
|
|
4500
|
-
reject(new Error('Unsupported message type'));
|
|
4501
|
-
}
|
|
4502
|
-
};
|
|
4503
|
-
window.addEventListener('message', messageHandler);
|
|
4504
|
-
const confirmationWindow = openPopupCenter({
|
|
4505
|
-
url: `${this.config.passportDomain}/transaction-confirmation`,
|
|
4506
|
-
title: CONFIRMATION_WINDOW_TITLE,
|
|
4507
|
-
width: popupOptions?.width || CONFIRMATION_WINDOW_WIDTH,
|
|
4508
|
-
height: popupOptions?.height || CONFIRMATION_WINDOW_HEIGHT,
|
|
4509
|
-
});
|
|
4510
|
-
// https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
|
|
4511
|
-
const timer = setInterval(() => {
|
|
4512
|
-
if (confirmationWindow.closed) {
|
|
4513
|
-
clearInterval(timer);
|
|
4514
|
-
window.removeEventListener('message', messageHandler);
|
|
4515
|
-
resolve({ confirmed: false });
|
|
4516
|
-
}
|
|
4517
|
-
}, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
|
|
4518
|
-
});
|
|
4519
|
-
}
|
|
4520
|
-
startGuardianTransaction(transactionId) {
|
|
4521
|
-
return new Promise((resolve, reject) => {
|
|
4522
|
-
const messageHandler = ({ data, origin }) => {
|
|
4523
|
-
if (origin !== this.config.passportDomain
|
|
4524
|
-
|| data.eventType !== PASSPORT_EVENT_TYPE) {
|
|
4525
|
-
return;
|
|
4526
|
-
}
|
|
4527
|
-
switch (data.messageType) {
|
|
4528
|
-
case ReceiveMessage.CONFIRMATION_WINDOW_READY: {
|
|
4529
|
-
break;
|
|
4530
|
-
}
|
|
4531
|
-
case ReceiveMessage.TRANSACTION_CONFIRMED: {
|
|
4532
|
-
resolve({ confirmed: true });
|
|
4533
|
-
break;
|
|
4534
|
-
}
|
|
4535
|
-
case ReceiveMessage.TRANSACTION_ERROR: {
|
|
4536
|
-
reject(new Error('Transaction error'));
|
|
4537
|
-
break;
|
|
4538
|
-
}
|
|
4539
|
-
default:
|
|
4540
|
-
reject(new Error('Unsupported message type'));
|
|
4541
|
-
}
|
|
4542
|
-
};
|
|
4543
|
-
window.addEventListener('message', messageHandler);
|
|
4544
|
-
if (!this.confirmationWindow) {
|
|
4545
|
-
resolve({ confirmed: false });
|
|
4546
|
-
return;
|
|
4547
|
-
}
|
|
4548
|
-
// eslint-disable-next-line max-len
|
|
4549
|
-
this.confirmationWindow.location.href = `${this.config.passportDomain}/transaction-confirmation/transaction.html?transactionId=${transactionId}&chainType=starkex`;
|
|
4550
|
-
// https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
|
|
4551
|
-
const timer = setInterval(() => {
|
|
4552
|
-
if (this.confirmationWindow?.closed) {
|
|
4553
|
-
clearInterval(timer);
|
|
4554
|
-
window.removeEventListener('message', messageHandler);
|
|
4555
|
-
resolve({ confirmed: false });
|
|
4556
|
-
}
|
|
4557
|
-
}, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
|
|
4558
|
-
});
|
|
4559
|
-
}
|
|
4560
|
-
loading(popupOptions) {
|
|
4561
|
-
this.confirmationWindow = openPopupCenter({
|
|
4562
|
-
url: `${this.config.passportDomain}/transaction-confirmation/loading.html`,
|
|
4563
|
-
title: CONFIRMATION_WINDOW_TITLE,
|
|
4564
|
-
width: popupOptions?.width || CONFIRMATION_WINDOW_WIDTH,
|
|
4565
|
-
height: popupOptions?.height || CONFIRMATION_WINDOW_HEIGHT,
|
|
4566
|
-
});
|
|
4567
|
-
}
|
|
4568
|
-
closeWindow() {
|
|
4569
|
-
this.confirmationWindow?.close();
|
|
4570
|
-
}
|
|
4571
|
-
}
|
|
4572
|
-
|
|
4573
4527
|
const ERC721$1 = 'ERC721';
|
|
4574
|
-
async function createOrder({ starkSigner, user, request, ordersApi,
|
|
4528
|
+
async function createOrder({ starkSigner, user, request, ordersApi, guardianClient, }) {
|
|
4575
4529
|
return withPassportError(async () => {
|
|
4576
4530
|
const { ethAddress } = user.imx;
|
|
4577
4531
|
const amountSell = request.sell.type === ERC721$1 ? '1' : request.sell.amount;
|
|
4578
4532
|
const amountBuy = request.buy.type === ERC721$1 ? '1' : request.buy.amount;
|
|
4533
|
+
const headers = {
|
|
4534
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
4535
|
+
Authorization: `Bearer ${user.accessToken}`,
|
|
4536
|
+
};
|
|
4579
4537
|
const getSignableOrderRequestV3 = {
|
|
4580
4538
|
user: ethAddress,
|
|
4581
4539
|
amount_buy: amountBuy,
|
|
@@ -4587,14 +4545,10 @@ async function createOrder({ starkSigner, user, request, ordersApi, confirmation
|
|
|
4587
4545
|
};
|
|
4588
4546
|
const getSignableOrderResponse = await ordersApi.getSignableOrder({
|
|
4589
4547
|
getSignableOrderRequestV3,
|
|
4548
|
+
}, { headers });
|
|
4549
|
+
await guardianClient.validate({
|
|
4550
|
+
payloadHash: getSignableOrderResponse.data.payload_hash,
|
|
4590
4551
|
});
|
|
4591
|
-
const confirmationResult = await confirmationScreen.startTransaction(user.accessToken, {
|
|
4592
|
-
transactionType: TransactionTypes.createOrder,
|
|
4593
|
-
transactionData: getSignableOrderRequestV3,
|
|
4594
|
-
});
|
|
4595
|
-
if (!confirmationResult.confirmed) {
|
|
4596
|
-
throw new Error('Transaction rejected by user');
|
|
4597
|
-
}
|
|
4598
4552
|
const { payload_hash: payloadHash } = getSignableOrderResponse.data;
|
|
4599
4553
|
const starkSignature = await starkSigner.signMessage(payloadHash);
|
|
4600
4554
|
const signableResultData = getSignableOrderResponse.data;
|
|
@@ -4614,11 +4568,7 @@ async function createOrder({ starkSigner, user, request, ordersApi, confirmation
|
|
|
4614
4568
|
vault_id_sell: signableResultData.vault_id_sell,
|
|
4615
4569
|
},
|
|
4616
4570
|
};
|
|
4617
|
-
const
|
|
4618
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
4619
|
-
Authorization: `Bearer ${user.accessToken}`,
|
|
4620
|
-
};
|
|
4621
|
-
const createOrderResponse = await ordersApi.createOrder(orderParams, {
|
|
4571
|
+
const createOrderResponse = await ordersApi.createOrderV3(orderParams, {
|
|
4622
4572
|
headers,
|
|
4623
4573
|
});
|
|
4624
4574
|
return {
|
|
@@ -4626,28 +4576,24 @@ async function createOrder({ starkSigner, user, request, ordersApi, confirmation
|
|
|
4626
4576
|
};
|
|
4627
4577
|
}, PassportErrorType.CREATE_ORDER_ERROR);
|
|
4628
4578
|
}
|
|
4629
|
-
async function cancelOrder({ user, starkSigner, request, ordersApi,
|
|
4579
|
+
async function cancelOrder({ user, starkSigner, request, ordersApi, guardianClient, }) {
|
|
4630
4580
|
return withPassportError(async () => {
|
|
4631
4581
|
const getSignableCancelOrderRequest = {
|
|
4632
4582
|
order_id: request.order_id,
|
|
4633
4583
|
};
|
|
4634
|
-
const getSignableCancelOrderResponse = await ordersApi.getSignableCancelOrder({
|
|
4635
|
-
getSignableCancelOrderRequest,
|
|
4636
|
-
});
|
|
4637
|
-
const confirmationResult = await confirmationScreen.startTransaction(user.accessToken, {
|
|
4638
|
-
transactionType: TransactionTypes.cancelOrder,
|
|
4639
|
-
transactionData: getSignableCancelOrderRequest,
|
|
4640
|
-
});
|
|
4641
|
-
if (!confirmationResult.confirmed) {
|
|
4642
|
-
throw new Error('Transaction rejected by user');
|
|
4643
|
-
}
|
|
4644
|
-
const { payload_hash: payloadHash } = getSignableCancelOrderResponse.data;
|
|
4645
|
-
const starkSignature = await starkSigner.signMessage(payloadHash);
|
|
4646
4584
|
const headers = {
|
|
4647
4585
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
4648
4586
|
Authorization: `Bearer ${user.accessToken}`,
|
|
4649
4587
|
};
|
|
4650
|
-
const
|
|
4588
|
+
const getSignableCancelOrderResponse = await ordersApi.getSignableCancelOrderV3({
|
|
4589
|
+
getSignableCancelOrderRequest,
|
|
4590
|
+
}, { headers });
|
|
4591
|
+
await guardianClient.validate({
|
|
4592
|
+
payloadHash: getSignableCancelOrderResponse.data.payload_hash,
|
|
4593
|
+
});
|
|
4594
|
+
const { payload_hash: payloadHash } = getSignableCancelOrderResponse.data;
|
|
4595
|
+
const starkSignature = await starkSigner.signMessage(payloadHash);
|
|
4596
|
+
const cancelOrderResponse = await ordersApi.cancelOrderV3({
|
|
4651
4597
|
id: request.order_id.toString(),
|
|
4652
4598
|
cancelOrderRequest: {
|
|
4653
4599
|
order_id: request.order_id,
|
|
@@ -4687,7 +4633,7 @@ async function registerPassport({ ethSigner, starkSigner, usersApi }, authorizat
|
|
|
4687
4633
|
}, PassportErrorType.USER_REGISTRATION_ERROR);
|
|
4688
4634
|
}
|
|
4689
4635
|
|
|
4690
|
-
async function createTrade({ request, tradesApi, user, starkSigner,
|
|
4636
|
+
async function createTrade({ request, tradesApi, user, starkSigner, guardianClient, }) {
|
|
4691
4637
|
return withPassportError(async () => {
|
|
4692
4638
|
const { ethAddress } = user.imx;
|
|
4693
4639
|
const getSignableTradeRequest = {
|
|
@@ -4696,16 +4642,14 @@ async function createTrade({ request, tradesApi, user, starkSigner, confirmation
|
|
|
4696
4642
|
order_id: request.order_id,
|
|
4697
4643
|
user: ethAddress,
|
|
4698
4644
|
};
|
|
4645
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
4646
|
+
const headers = { Authorization: `Bearer ${user.accessToken}` };
|
|
4699
4647
|
const getSignableTradeResponse = await tradesApi.getSignableTrade({
|
|
4700
4648
|
getSignableTradeRequest,
|
|
4649
|
+
}, { headers });
|
|
4650
|
+
await guardianClient.validate({
|
|
4651
|
+
payloadHash: getSignableTradeResponse.data.payload_hash,
|
|
4701
4652
|
});
|
|
4702
|
-
const confirmationResult = await confirmationScreen.startTransaction(user.accessToken, {
|
|
4703
|
-
transactionType: TransactionTypes.createTrade,
|
|
4704
|
-
transactionData: getSignableTradeRequest,
|
|
4705
|
-
});
|
|
4706
|
-
if (!confirmationResult.confirmed) {
|
|
4707
|
-
throw new Error('Transaction rejected by user');
|
|
4708
|
-
}
|
|
4709
4653
|
const { payload_hash: payloadHash } = getSignableTradeResponse.data;
|
|
4710
4654
|
const starkSignature = await starkSigner.signMessage(payloadHash);
|
|
4711
4655
|
const { data: signableResultData } = getSignableTradeResponse;
|
|
@@ -4727,8 +4671,6 @@ async function createTrade({ request, tradesApi, user, starkSigner, confirmation
|
|
|
4727
4671
|
vault_id_sell: signableResultData.vault_id_sell,
|
|
4728
4672
|
},
|
|
4729
4673
|
};
|
|
4730
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
4731
|
-
const headers = { Authorization: `Bearer ${user.accessToken}` };
|
|
4732
4674
|
const { data: createTradeResponse } = await tradesApi.createTradeV3(tradeParams, {
|
|
4733
4675
|
headers,
|
|
4734
4676
|
});
|
|
@@ -4736,66 +4678,8 @@ async function createTrade({ request, tradesApi, user, starkSigner, confirmation
|
|
|
4736
4678
|
}, PassportErrorType.CREATE_TRADE_ERROR);
|
|
4737
4679
|
}
|
|
4738
4680
|
|
|
4739
|
-
const POLL_INTERVAL = 1 * 1000; // every 1 second
|
|
4740
|
-
const MAX_RETRIES = 3;
|
|
4741
|
-
const wait = (ms) => new Promise((resolve) => {
|
|
4742
|
-
setTimeout(() => resolve(), ms);
|
|
4743
|
-
});
|
|
4744
|
-
const retryWithDelay = async (fn, options) => {
|
|
4745
|
-
const { retries = MAX_RETRIES, interval = POLL_INTERVAL, finalErr = Error('Retry failed'), finallyFn = () => { }, } = options || {};
|
|
4746
|
-
try {
|
|
4747
|
-
return await fn();
|
|
4748
|
-
}
|
|
4749
|
-
catch (err) {
|
|
4750
|
-
if (retries <= 0) {
|
|
4751
|
-
return Promise.reject(finalErr);
|
|
4752
|
-
}
|
|
4753
|
-
await wait(interval);
|
|
4754
|
-
return retryWithDelay(fn, { retries: retries - 1, finalErr, finallyFn });
|
|
4755
|
-
}
|
|
4756
|
-
finally {
|
|
4757
|
-
if (retries <= 0) {
|
|
4758
|
-
finallyFn();
|
|
4759
|
-
}
|
|
4760
|
-
}
|
|
4761
|
-
};
|
|
4762
|
-
|
|
4763
4681
|
const ERC721 = 'ERC721';
|
|
4764
|
-
|
|
4765
|
-
confirmationScreen.loading();
|
|
4766
|
-
const transactionAPI = new TransactionsApi(new Configuration({
|
|
4767
|
-
accessToken,
|
|
4768
|
-
basePath: imxPublicApiDomain,
|
|
4769
|
-
}));
|
|
4770
|
-
const starkExTransactionApi = new StarkexTransactionsApi(new Configuration({
|
|
4771
|
-
accessToken,
|
|
4772
|
-
basePath: imxPublicApiDomain,
|
|
4773
|
-
}));
|
|
4774
|
-
const finallyFn = () => {
|
|
4775
|
-
confirmationScreen.closeWindow();
|
|
4776
|
-
};
|
|
4777
|
-
const transactionRes = await retryWithDelay(async () => transactionAPI.getTransactionByID({
|
|
4778
|
-
transactionID: payloadHash,
|
|
4779
|
-
chainType: 'starkex',
|
|
4780
|
-
}), { finallyFn });
|
|
4781
|
-
if (!transactionRes.data.id) {
|
|
4782
|
-
throw new Error("Transaction doesn't exists");
|
|
4783
|
-
}
|
|
4784
|
-
const evaluateStarkexRes = await starkExTransactionApi.evaluateStarkexTransaction({
|
|
4785
|
-
payloadHash,
|
|
4786
|
-
});
|
|
4787
|
-
const { confirmationRequired } = evaluateStarkexRes.data;
|
|
4788
|
-
if (confirmationRequired) {
|
|
4789
|
-
const confirmationResult = await confirmationScreen.startGuardianTransaction(payloadHash);
|
|
4790
|
-
if (!confirmationResult.confirmed) {
|
|
4791
|
-
throw new Error('Transaction rejected by user');
|
|
4792
|
-
}
|
|
4793
|
-
}
|
|
4794
|
-
else {
|
|
4795
|
-
confirmationScreen.closeWindow();
|
|
4796
|
-
}
|
|
4797
|
-
};
|
|
4798
|
-
async function transfer({ request, transfersApi, starkSigner, user, imxPublicApiDomain, confirmationScreen, }) {
|
|
4682
|
+
async function transfer({ request, transfersApi, starkSigner, user, guardianClient, }) {
|
|
4799
4683
|
return withPassportError(async () => {
|
|
4800
4684
|
const transferAmount = request.type === ERC721 ? '1' : request.amount;
|
|
4801
4685
|
const getSignableTransferRequest = {
|
|
@@ -4810,11 +4694,8 @@ async function transfer({ request, transfersApi, starkSigner, user, imxPublicApi
|
|
|
4810
4694
|
const signableResult = await transfersApi.getSignableTransferV1({
|
|
4811
4695
|
getSignableTransferRequest,
|
|
4812
4696
|
}, { headers });
|
|
4813
|
-
await
|
|
4814
|
-
imxPublicApiDomain,
|
|
4815
|
-
accessToken: user.accessToken,
|
|
4697
|
+
await guardianClient.validate({
|
|
4816
4698
|
payloadHash: signableResult.data.payload_hash,
|
|
4817
|
-
confirmationScreen,
|
|
4818
4699
|
});
|
|
4819
4700
|
const signableResultData = signableResult.data;
|
|
4820
4701
|
const { payload_hash: payloadHash } = signableResultData;
|
|
@@ -4843,7 +4724,7 @@ async function transfer({ request, transfersApi, starkSigner, user, imxPublicApi
|
|
|
4843
4724
|
};
|
|
4844
4725
|
}, PassportErrorType.TRANSFER_ERROR);
|
|
4845
4726
|
}
|
|
4846
|
-
async function batchNftTransfer({ user, starkSigner, request, transfersApi,
|
|
4727
|
+
async function batchNftTransfer({ user, starkSigner, request, transfersApi, guardianClient, }) {
|
|
4847
4728
|
return withPassportError(async () => {
|
|
4848
4729
|
const { ethAddress } = user.imx;
|
|
4849
4730
|
const signableRequests = request.map((nftTransfer) => ({
|
|
@@ -4859,17 +4740,18 @@ async function batchNftTransfer({ user, starkSigner, request, transfersApi, conf
|
|
|
4859
4740
|
sender_ether_key: ethAddress,
|
|
4860
4741
|
signable_requests: signableRequests,
|
|
4861
4742
|
};
|
|
4743
|
+
const headers = {
|
|
4744
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
4745
|
+
Authorization: `Bearer ${user.accessToken}`,
|
|
4746
|
+
};
|
|
4862
4747
|
const signableResult = await transfersApi.getSignableTransfer({
|
|
4863
4748
|
getSignableTransferRequestV2,
|
|
4864
|
-
});
|
|
4749
|
+
}, { headers });
|
|
4865
4750
|
const popupWindowSize = { width: 480, height: 784 };
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
}
|
|
4870
|
-
if (!confirmationResult.confirmed) {
|
|
4871
|
-
throw new Error('Transaction rejected by user');
|
|
4872
|
-
}
|
|
4751
|
+
await guardianClient.validate({
|
|
4752
|
+
payloadHash: signableResult.data.signable_responses[0]?.payload_hash,
|
|
4753
|
+
popupWindowSize,
|
|
4754
|
+
});
|
|
4873
4755
|
const requests = await Promise.all(signableResult.data.signable_responses.map(async (resp) => {
|
|
4874
4756
|
const starkSignature = await starkSigner.signMessage(resp.payload_hash);
|
|
4875
4757
|
return {
|
|
@@ -4887,10 +4769,6 @@ async function batchNftTransfer({ user, starkSigner, request, transfersApi, conf
|
|
|
4887
4769
|
sender_stark_key: signableResult.data.sender_stark_key,
|
|
4888
4770
|
requests,
|
|
4889
4771
|
};
|
|
4890
|
-
const headers = {
|
|
4891
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
4892
|
-
Authorization: `Bearer ${user.accessToken}`,
|
|
4893
|
-
};
|
|
4894
4772
|
const response = await transfersApi.createTransfer({
|
|
4895
4773
|
createTransferRequestV2: transferSigningParams,
|
|
4896
4774
|
}, { headers });
|
|
@@ -4905,13 +4783,18 @@ class PassportImxProvider {
|
|
|
4905
4783
|
starkSigner;
|
|
4906
4784
|
immutableXClient;
|
|
4907
4785
|
confirmationScreen;
|
|
4908
|
-
|
|
4786
|
+
guardianClient;
|
|
4909
4787
|
constructor({ user, starkSigner, immutableXClient, imxPublicApiDomain, confirmationScreen, }) {
|
|
4910
4788
|
this.user = user;
|
|
4911
4789
|
this.starkSigner = starkSigner;
|
|
4912
4790
|
this.immutableXClient = immutableXClient;
|
|
4913
|
-
this.imxPublicApiDomain = imxPublicApiDomain;
|
|
4914
4791
|
this.confirmationScreen = confirmationScreen;
|
|
4792
|
+
this.guardianClient = new GuardianClient({
|
|
4793
|
+
imxPublicApiDomain,
|
|
4794
|
+
accessToken: user.accessToken,
|
|
4795
|
+
confirmationScreen,
|
|
4796
|
+
imxEtherAddress: user.imx.ethAddress,
|
|
4797
|
+
});
|
|
4915
4798
|
}
|
|
4916
4799
|
async transfer(request) {
|
|
4917
4800
|
return transfer({
|
|
@@ -4919,8 +4802,7 @@ class PassportImxProvider {
|
|
|
4919
4802
|
user: this.user,
|
|
4920
4803
|
starkSigner: this.starkSigner,
|
|
4921
4804
|
transfersApi: this.immutableXClient.transfersApi,
|
|
4922
|
-
|
|
4923
|
-
imxPublicApiDomain: this.imxPublicApiDomain,
|
|
4805
|
+
guardianClient: this.guardianClient,
|
|
4924
4806
|
});
|
|
4925
4807
|
}
|
|
4926
4808
|
// TODO: Remove once implemented
|
|
@@ -4939,7 +4821,7 @@ class PassportImxProvider {
|
|
|
4939
4821
|
user: this.user,
|
|
4940
4822
|
starkSigner: this.starkSigner,
|
|
4941
4823
|
ordersApi: this.immutableXClient.ordersApi,
|
|
4942
|
-
|
|
4824
|
+
guardianClient: this.guardianClient,
|
|
4943
4825
|
});
|
|
4944
4826
|
}
|
|
4945
4827
|
cancelOrder(request) {
|
|
@@ -4948,7 +4830,7 @@ class PassportImxProvider {
|
|
|
4948
4830
|
user: this.user,
|
|
4949
4831
|
starkSigner: this.starkSigner,
|
|
4950
4832
|
ordersApi: this.immutableXClient.ordersApi,
|
|
4951
|
-
|
|
4833
|
+
guardianClient: this.guardianClient,
|
|
4952
4834
|
});
|
|
4953
4835
|
}
|
|
4954
4836
|
createTrade(request) {
|
|
@@ -4957,7 +4839,7 @@ class PassportImxProvider {
|
|
|
4957
4839
|
user: this.user,
|
|
4958
4840
|
starkSigner: this.starkSigner,
|
|
4959
4841
|
tradesApi: this.immutableXClient.tradesApi,
|
|
4960
|
-
|
|
4842
|
+
guardianClient: this.guardianClient,
|
|
4961
4843
|
});
|
|
4962
4844
|
}
|
|
4963
4845
|
batchNftTransfer(request) {
|
|
@@ -4966,7 +4848,7 @@ class PassportImxProvider {
|
|
|
4966
4848
|
user: this.user,
|
|
4967
4849
|
starkSigner: this.starkSigner,
|
|
4968
4850
|
transfersApi: this.immutableXClient.transfersApi,
|
|
4969
|
-
|
|
4851
|
+
guardianClient: this.guardianClient,
|
|
4970
4852
|
});
|
|
4971
4853
|
}
|
|
4972
4854
|
exchangeTransfer(request) {
|
|
@@ -5149,6 +5031,159 @@ class PassportConfiguration {
|
|
|
5149
5031
|
}
|
|
5150
5032
|
}
|
|
5151
5033
|
|
|
5034
|
+
var ReceiveMessage;
|
|
5035
|
+
(function (ReceiveMessage) {
|
|
5036
|
+
ReceiveMessage["CONFIRMATION_WINDOW_READY"] = "confirmation_window_ready";
|
|
5037
|
+
ReceiveMessage["TRANSACTION_CONFIRMED"] = "transaction_confirmed";
|
|
5038
|
+
ReceiveMessage["TRANSACTION_ERROR"] = "transaction_error";
|
|
5039
|
+
})(ReceiveMessage || (ReceiveMessage = {}));
|
|
5040
|
+
var SendMessage;
|
|
5041
|
+
(function (SendMessage) {
|
|
5042
|
+
SendMessage["TRANSACTION_START"] = "transaction_start";
|
|
5043
|
+
})(SendMessage || (SendMessage = {}));
|
|
5044
|
+
var TransactionTypes;
|
|
5045
|
+
(function (TransactionTypes) {
|
|
5046
|
+
TransactionTypes["cancelOrder"] = "delete:v1/orders";
|
|
5047
|
+
TransactionTypes["createOrder"] = "post:v1/orders";
|
|
5048
|
+
TransactionTypes["createTrade"] = "post:v1/trades";
|
|
5049
|
+
TransactionTypes["createTransfer"] = "post:v1/transfers";
|
|
5050
|
+
TransactionTypes["createBatchTransfer"] = "post:v2/transfers";
|
|
5051
|
+
})(TransactionTypes || (TransactionTypes = {}));
|
|
5052
|
+
const PASSPORT_EVENT_TYPE = 'imx_passport_confirmation';
|
|
5053
|
+
|
|
5054
|
+
const openPopupCenter = ({ url, title, width, height, }) => {
|
|
5055
|
+
const left = Math.max(0, Math.round(window.screenX + (window.outerWidth - width) / 2));
|
|
5056
|
+
const top = Math.max(0, Math.round(window.screenY + (window.outerHeight - height) / 2));
|
|
5057
|
+
const newWindow = window.open(url, title, `
|
|
5058
|
+
scrollbars=yes,
|
|
5059
|
+
width=${width},
|
|
5060
|
+
height=${height},
|
|
5061
|
+
top=${top},
|
|
5062
|
+
left=${left}
|
|
5063
|
+
`);
|
|
5064
|
+
if (!newWindow) {
|
|
5065
|
+
throw new Error('Failed to open confirmation screen');
|
|
5066
|
+
}
|
|
5067
|
+
newWindow.focus();
|
|
5068
|
+
return newWindow;
|
|
5069
|
+
};
|
|
5070
|
+
|
|
5071
|
+
const CONFIRMATION_WINDOW_TITLE = 'Confirm this transaction';
|
|
5072
|
+
const CONFIRMATION_WINDOW_HEIGHT = 380;
|
|
5073
|
+
const CONFIRMATION_WINDOW_WIDTH = 480;
|
|
5074
|
+
const CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION = 1000;
|
|
5075
|
+
class ConfirmationScreen {
|
|
5076
|
+
config;
|
|
5077
|
+
confirmationWindow;
|
|
5078
|
+
constructor(config) {
|
|
5079
|
+
this.config = config;
|
|
5080
|
+
}
|
|
5081
|
+
postMessage(destinationWindow, accessToken, message) {
|
|
5082
|
+
destinationWindow.postMessage({
|
|
5083
|
+
eventType: PASSPORT_EVENT_TYPE,
|
|
5084
|
+
accessToken,
|
|
5085
|
+
...message,
|
|
5086
|
+
}, this.config.passportDomain);
|
|
5087
|
+
}
|
|
5088
|
+
startTransaction(accessToken, transaction, popupOptions) {
|
|
5089
|
+
return new Promise((resolve, reject) => {
|
|
5090
|
+
const messageHandler = ({ data, origin }) => {
|
|
5091
|
+
if (origin !== this.config.passportDomain
|
|
5092
|
+
|| data.eventType !== PASSPORT_EVENT_TYPE) {
|
|
5093
|
+
return;
|
|
5094
|
+
}
|
|
5095
|
+
switch (data.messageType) {
|
|
5096
|
+
case ReceiveMessage.CONFIRMATION_WINDOW_READY: {
|
|
5097
|
+
// TODO: remove once fixed
|
|
5098
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
5099
|
+
this.postMessage(confirmationWindow, accessToken, {
|
|
5100
|
+
messageType: SendMessage.TRANSACTION_START,
|
|
5101
|
+
messageData: transaction,
|
|
5102
|
+
});
|
|
5103
|
+
break;
|
|
5104
|
+
}
|
|
5105
|
+
case ReceiveMessage.TRANSACTION_CONFIRMED: {
|
|
5106
|
+
resolve({ confirmed: true });
|
|
5107
|
+
break;
|
|
5108
|
+
}
|
|
5109
|
+
case ReceiveMessage.TRANSACTION_ERROR: {
|
|
5110
|
+
reject(new Error('Transaction error'));
|
|
5111
|
+
break;
|
|
5112
|
+
}
|
|
5113
|
+
default:
|
|
5114
|
+
reject(new Error('Unsupported message type'));
|
|
5115
|
+
}
|
|
5116
|
+
};
|
|
5117
|
+
window.addEventListener('message', messageHandler);
|
|
5118
|
+
const confirmationWindow = openPopupCenter({
|
|
5119
|
+
url: `${this.config.passportDomain}/transaction-confirmation`,
|
|
5120
|
+
title: CONFIRMATION_WINDOW_TITLE,
|
|
5121
|
+
width: popupOptions?.width || CONFIRMATION_WINDOW_WIDTH,
|
|
5122
|
+
height: popupOptions?.height || CONFIRMATION_WINDOW_HEIGHT,
|
|
5123
|
+
});
|
|
5124
|
+
// https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
|
|
5125
|
+
const timer = setInterval(() => {
|
|
5126
|
+
if (confirmationWindow.closed) {
|
|
5127
|
+
clearInterval(timer);
|
|
5128
|
+
window.removeEventListener('message', messageHandler);
|
|
5129
|
+
resolve({ confirmed: false });
|
|
5130
|
+
}
|
|
5131
|
+
}, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
|
|
5132
|
+
});
|
|
5133
|
+
}
|
|
5134
|
+
startGuardianTransaction(transactionId, imxEtherAddress) {
|
|
5135
|
+
return new Promise((resolve, reject) => {
|
|
5136
|
+
const messageHandler = ({ data, origin }) => {
|
|
5137
|
+
if (origin !== this.config.passportDomain
|
|
5138
|
+
|| data.eventType !== PASSPORT_EVENT_TYPE) {
|
|
5139
|
+
return;
|
|
5140
|
+
}
|
|
5141
|
+
switch (data.messageType) {
|
|
5142
|
+
case ReceiveMessage.CONFIRMATION_WINDOW_READY: {
|
|
5143
|
+
break;
|
|
5144
|
+
}
|
|
5145
|
+
case ReceiveMessage.TRANSACTION_CONFIRMED: {
|
|
5146
|
+
resolve({ confirmed: true });
|
|
5147
|
+
break;
|
|
5148
|
+
}
|
|
5149
|
+
case ReceiveMessage.TRANSACTION_ERROR: {
|
|
5150
|
+
reject(new Error('Transaction error'));
|
|
5151
|
+
break;
|
|
5152
|
+
}
|
|
5153
|
+
default:
|
|
5154
|
+
reject(new Error('Unsupported message type'));
|
|
5155
|
+
}
|
|
5156
|
+
};
|
|
5157
|
+
window.addEventListener('message', messageHandler);
|
|
5158
|
+
if (!this.confirmationWindow) {
|
|
5159
|
+
resolve({ confirmed: false });
|
|
5160
|
+
return;
|
|
5161
|
+
}
|
|
5162
|
+
// eslint-disable-next-line max-len
|
|
5163
|
+
this.confirmationWindow.location.href = `${this.config.passportDomain}/transaction-confirmation/transaction.html?transactionId=${transactionId}&imxEtherAddress=${imxEtherAddress}&chainType=starkex`;
|
|
5164
|
+
// https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
|
|
5165
|
+
const timer = setInterval(() => {
|
|
5166
|
+
if (this.confirmationWindow?.closed) {
|
|
5167
|
+
clearInterval(timer);
|
|
5168
|
+
window.removeEventListener('message', messageHandler);
|
|
5169
|
+
resolve({ confirmed: false });
|
|
5170
|
+
}
|
|
5171
|
+
}, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
|
|
5172
|
+
});
|
|
5173
|
+
}
|
|
5174
|
+
loading(popupOptions) {
|
|
5175
|
+
this.confirmationWindow = openPopupCenter({
|
|
5176
|
+
url: `${this.config.passportDomain}/transaction-confirmation/loading.html`,
|
|
5177
|
+
title: CONFIRMATION_WINDOW_TITLE,
|
|
5178
|
+
width: popupOptions?.width || CONFIRMATION_WINDOW_WIDTH,
|
|
5179
|
+
height: popupOptions?.height || CONFIRMATION_WINDOW_HEIGHT,
|
|
5180
|
+
});
|
|
5181
|
+
}
|
|
5182
|
+
closeWindow() {
|
|
5183
|
+
this.confirmationWindow?.close();
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5186
|
+
|
|
5152
5187
|
class Passport {
|
|
5153
5188
|
authManager;
|
|
5154
5189
|
config;
|