Re-export orderHashUtils
Rather than have hacks spread through the codebase
This commit is contained in:
parent
56310b7bd4
commit
d431790e19
@ -63,8 +63,8 @@
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "*",
|
||||
"@0x/contracts-test-utils": "^3.2.0-beta.3",
|
||||
"@0x/typescript-typings": "^4.4.0-beta.2",
|
||||
"@0x/contracts-test-utils": "^3.2.0-beta.3",
|
||||
"ethereum-types": "^2.2.0-beta.2",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
|
@ -1,27 +1,19 @@
|
||||
import { LogDecoder } from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as chai from 'chai';
|
||||
import { LogWithDecodedArgs, Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { ERC1155MintableContract, ERC1155TransferSingleEventArgs } from './wrappers';
|
||||
|
||||
import { artifacts } from './artifacts';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
export class Erc1155Wrapper {
|
||||
private readonly _erc1155Contract: ERC1155MintableContract;
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _contractOwner: string;
|
||||
private readonly _logDecoder: LogDecoder;
|
||||
|
||||
constructor(contractInstance: ERC1155MintableContract, provider: Provider, contractOwner: string) {
|
||||
this._erc1155Contract = contractInstance;
|
||||
this._web3Wrapper = new Web3Wrapper(provider);
|
||||
this._contractOwner = contractOwner;
|
||||
this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts);
|
||||
}
|
||||
public getContract(): ERC1155MintableContract {
|
||||
return this._erc1155Contract;
|
||||
@ -40,11 +32,11 @@ export class Erc1155Wrapper {
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const spender = delegatedSpender === undefined ? from : delegatedSpender;
|
||||
const callbackDataHex = callbackData === undefined ? '0x' : callbackData;
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
|
||||
await this._erc1155Contract.safeTransferFrom(from, to, token, value, callbackDataHex).sendTransactionAsync({
|
||||
const tx = await this._erc1155Contract
|
||||
.safeTransferFrom(from, to, token, value, callbackDataHex)
|
||||
.awaitTransactionSuccessAsync({
|
||||
from: spender,
|
||||
}),
|
||||
);
|
||||
});
|
||||
return tx;
|
||||
}
|
||||
public async safeBatchTransferFromAsync(
|
||||
@ -57,11 +49,9 @@ export class Erc1155Wrapper {
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const spender = delegatedSpender === undefined ? from : delegatedSpender;
|
||||
const callbackDataHex = callbackData === undefined ? '0x' : callbackData;
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
|
||||
await this._erc1155Contract
|
||||
.safeBatchTransferFrom(from, to, tokens, values, callbackDataHex)
|
||||
.sendTransactionAsync({ from: spender }),
|
||||
);
|
||||
const tx = await this._erc1155Contract
|
||||
.safeBatchTransferFrom(from, to, tokens, values, callbackDataHex)
|
||||
.awaitTransactionSuccessAsync({ from: spender });
|
||||
return tx;
|
||||
}
|
||||
public async mintFungibleTokensAsync(
|
||||
@ -70,11 +60,9 @@ export class Erc1155Wrapper {
|
||||
): Promise<BigNumber> {
|
||||
const tokenUri = 'dummyFungibleToken';
|
||||
const tokenIsNonFungible = false;
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
|
||||
await this._erc1155Contract.create(tokenUri, tokenIsNonFungible).sendTransactionAsync({
|
||||
from: this._contractOwner,
|
||||
}),
|
||||
);
|
||||
const tx = await this._erc1155Contract.create(tokenUri, tokenIsNonFungible).awaitTransactionSuccessAsync({
|
||||
from: this._contractOwner,
|
||||
});
|
||||
// tslint:disable-next-line no-unnecessary-type-assertion
|
||||
const createFungibleTokenLog = tx.logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>;
|
||||
const tokenId = createFungibleTokenLog.args.id;
|
||||
@ -99,11 +87,9 @@ export class Erc1155Wrapper {
|
||||
public async mintNonFungibleTokensAsync(beneficiaries: string[]): Promise<[BigNumber, BigNumber[]]> {
|
||||
const tokenUri = 'dummyNonFungibleToken';
|
||||
const tokenIsNonFungible = true;
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
|
||||
await this._erc1155Contract.create(tokenUri, tokenIsNonFungible).sendTransactionAsync({
|
||||
from: this._contractOwner,
|
||||
}),
|
||||
);
|
||||
const tx = await this._erc1155Contract.create(tokenUri, tokenIsNonFungible).awaitTransactionSuccessAsync({
|
||||
from: this._contractOwner,
|
||||
});
|
||||
// tslint:disable-next-line no-unnecessary-type-assertion
|
||||
const createFungibleTokenLog = tx.logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>;
|
||||
const token = createFungibleTokenLog.args.id;
|
||||
@ -125,11 +111,9 @@ export class Erc1155Wrapper {
|
||||
beneficiary: string,
|
||||
isApproved: boolean,
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
|
||||
await this._erc1155Contract.setApprovalForAll(beneficiary, isApproved).sendTransactionAsync({
|
||||
from: owner,
|
||||
}),
|
||||
);
|
||||
const tx = await this._erc1155Contract.setApprovalForAll(beneficiary, isApproved).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
return tx;
|
||||
}
|
||||
public async isApprovedForAllAsync(owner: string, beneficiary: string): Promise<boolean> {
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
import { DevUtilsContract, ExchangeContract } from '@0x/abi-gen-wrappers';
|
||||
import { DevUtilsContract } from '@0x/abi-gen-wrappers';
|
||||
import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import { SignedOrder } from '@0x/order-utils';
|
||||
@ -37,7 +37,6 @@ export class SwapQuoter {
|
||||
private readonly _protocolFeeUtils: ProtocolFeeUtils;
|
||||
private readonly _orderPruner: OrderPruner;
|
||||
private readonly _devUtilsContract: DevUtilsContract;
|
||||
private readonly _exchangeContract: ExchangeContract;
|
||||
/**
|
||||
* Instantiates a new SwapQuoter instance given existing liquidity in the form of orders and feeOrders.
|
||||
* @param supportedProvider The Provider instance you would like to use for interacting with the Ethereum network.
|
||||
@ -156,7 +155,6 @@ export class SwapQuoter {
|
||||
this.permittedOrderFeeTypes = permittedOrderFeeTypes;
|
||||
this._contractAddresses = getContractAddressesForChainOrThrow(chainId);
|
||||
this._devUtilsContract = new DevUtilsContract(this._contractAddresses.devUtils, provider);
|
||||
this._exchangeContract = new ExchangeContract(this._contractAddresses.exchange, provider);
|
||||
this._protocolFeeUtils = new ProtocolFeeUtils();
|
||||
this._orderPruner = new OrderPruner(this._devUtilsContract, {
|
||||
expiryBufferMs: this.expiryBufferMs,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DevUtilsContract, ERC20TokenContract, ExchangeContract, ForwarderContract } from '@0x/abi-gen-wrappers';
|
||||
import { DevUtilsContract, ERC20TokenContract, ForwarderContract } from '@0x/abi-gen-wrappers';
|
||||
import { ContractAddresses } from '@0x/contract-addresses';
|
||||
import { constants as devConstants, OrderFactory } from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
|
||||
@ -82,7 +82,6 @@ describe('ForwarderSwapQuoteConsumer', () => {
|
||||
let contractAddresses: ContractAddresses;
|
||||
let erc20TokenContract: ERC20TokenContract;
|
||||
let forwarderContract: ForwarderContract;
|
||||
let exchangeContract: ExchangeContract;
|
||||
|
||||
let orders: PrunedSignedOrder[];
|
||||
let invalidOrders: PrunedSignedOrder[];
|
||||
@ -104,7 +103,6 @@ describe('ForwarderSwapQuoteConsumer', () => {
|
||||
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
||||
erc20TokenContract = new ERC20TokenContract(makerTokenAddress, provider);
|
||||
forwarderContract = new ForwarderContract(contractAddresses.forwarder, provider);
|
||||
exchangeContract = new ExchangeContract(contractAddresses.exchange, provider);
|
||||
const devUtils = new DevUtilsContract(contractAddresses.devUtils, provider);
|
||||
[makerAssetData, takerAssetData, wethAssetData] = await Promise.all([
|
||||
devUtils.encodeERC20AssetData(makerTokenAddress).callAsync(),
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DevUtilsContract, ExchangeContract, WETH9Contract } from '@0x/abi-gen-wrappers';
|
||||
import { DevUtilsContract, WETH9Contract } from '@0x/abi-gen-wrappers';
|
||||
import { ContractAddresses } from '@0x/contract-addresses';
|
||||
import { constants as devConstants, OrderFactory } from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
|
||||
@ -69,7 +69,6 @@ const PARTIAL_LARGE_PRUNED_SIGNED_ORDERS: Array<Partial<PrunedSignedOrder>> = [
|
||||
describe('swapQuoteConsumerUtils', () => {
|
||||
let wethContract: WETH9Contract;
|
||||
let protocolFeeUtils: ProtocolFeeUtils;
|
||||
let exchangeContract: ExchangeContract;
|
||||
let userAddresses: string[];
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
@ -90,7 +89,6 @@ describe('swapQuoteConsumerUtils', () => {
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
const devUtils = new DevUtilsContract(contractAddresses.devUtils, provider);
|
||||
wethContract = new WETH9Contract(contractAddresses.etherToken, provider);
|
||||
exchangeContract = new ExchangeContract(contractAddresses.exchange, provider);
|
||||
[takerAddress, makerAddress] = userAddresses;
|
||||
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
||||
[makerAssetData, takerAssetData, wethAssetData] = [
|
||||
|
1504
packages/contract-artifacts/artifacts/DevUtils.json
generated
1504
packages/contract-artifacts/artifacts/DevUtils.json
generated
File diff suppressed because one or more lines are too long
@ -64,7 +64,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/abi-gen-wrappers": "^5.4.0-beta.3",
|
||||
"@0x/contracts-dev-utils": "^0.1.0-beta.3",
|
||||
"@0x/assert": "^2.2.0-beta.2",
|
||||
"@0x/contract-addresses": "^3.3.0-beta.4",
|
||||
"@0x/contract-artifacts": "^2.3.0-beta.3",
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { BigNumber, NULL_ADDRESS, NULL_BYTES } from '@0x/utils';
|
||||
import { MethodAbi } from 'ethereum-types';
|
||||
|
||||
const ERC20_METHOD_ABI: MethodAbi = {
|
||||
@ -84,8 +84,9 @@ const STATIC_CALL_METHOD_ABI: MethodAbi = {
|
||||
};
|
||||
|
||||
export const constants = {
|
||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||
NULL_BYTES: '0x',
|
||||
NULL_ADDRESS,
|
||||
FAKED_PROVIDER: { isEIP1193: true },
|
||||
NULL_BYTES,
|
||||
NULL_ERC20_ASSET_DATA: '0xf47261b00000000000000000000000000000000000000000000000000000000000000000',
|
||||
// tslint:disable-next-line:custom-no-magic-numbers
|
||||
UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { DevUtilsContract } from '@0x/abi-gen-wrappers';
|
||||
import { assert } from '@0x/assert';
|
||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import {
|
||||
EIP712DomainWithDefaultSchema,
|
||||
@ -112,9 +112,7 @@ export const eip712Utils = {
|
||||
version: constants.COORDINATOR_DOMAIN_VERSION,
|
||||
verifyingContract,
|
||||
};
|
||||
const transactionHash = await new DevUtilsContract('0x0000000000000000000000000000000000000000', {
|
||||
isEIP1193: true,
|
||||
} as any)
|
||||
const transactionHash = await new DevUtilsContract(constants.NULL_ADDRESS, constants.FAKED_PROVIDER as any)
|
||||
.getTransactionHash(
|
||||
transaction,
|
||||
new BigNumber(transaction.domain.chainId),
|
||||
|
@ -5,6 +5,7 @@ export { marketUtils } from './market_utils';
|
||||
export { rateUtils } from './rate_utils';
|
||||
export { sortingUtils } from './sorting_utils';
|
||||
export { orderCalculationUtils } from './order_calculation_utils';
|
||||
export { orderHashUtils } from './order_hash_utils';
|
||||
|
||||
export { eip712Utils } from './eip712_utils';
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
import { Order, SignedOrder } from '@0x/types';
|
||||
import { BigNumber, providerUtils } from '@0x/utils';
|
||||
import { SupportedProvider } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { constants } from './constants';
|
||||
import { orderHashUtils } from './order_hash_utils';
|
||||
import { generatePseudoRandomSalt } from './salt';
|
||||
import { signatureUtils } from './signature_utils';
|
||||
import { CreateOrderOpts } from './types';
|
||||
|
||||
export const orderFactory = {
|
||||
createOrderFromPartial(partialOrder: Partial<Order>): Order {
|
||||
const chainId: number = getChainIdFromPartial(partialOrder);
|
||||
@ -77,20 +77,16 @@ export const orderFactory = {
|
||||
await providerUtils.getChainIdAsync(supportedProvider),
|
||||
createOrderOpts,
|
||||
);
|
||||
const orderHash = await new DevUtilsContract('0x0000000000000000000000000000000000000000', {
|
||||
isEIP1193: true,
|
||||
} as any)
|
||||
.getOrderHash(order, new BigNumber(order.chainId), order.exchangeAddress)
|
||||
.callAsync();
|
||||
const orderHash = await orderHashUtils.getOrderHashAsync(order);
|
||||
const signature = await signatureUtils.ecSignHashAsync(supportedProvider, orderHash, makerAddress);
|
||||
const signedOrder: SignedOrder = _.assign(order, { signature });
|
||||
const signedOrder: SignedOrder = { ...order, signature };
|
||||
return signedOrder;
|
||||
},
|
||||
};
|
||||
|
||||
function getChainIdFromPartial(partialOrder: Partial<Order> | Partial<SignedOrder>): number {
|
||||
const chainId = partialOrder.chainId;
|
||||
if (!_.isNumber(chainId)) {
|
||||
if (chainId === undefined || !Number.isInteger(chainId)) {
|
||||
throw new Error('chainId must be valid');
|
||||
}
|
||||
return chainId;
|
||||
|
16
packages/order-utils/src/order_hash_utils.ts
Normal file
16
packages/order-utils/src/order_hash_utils.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { DevUtilsContract } from '@0x/abi-gen-wrappers';
|
||||
import { Order } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { constants } from './constants';
|
||||
|
||||
const devUtilsContract = new DevUtilsContract(constants.NULL_ADDRESS, constants.FAKED_PROVIDER as any);
|
||||
|
||||
export const orderHashUtils = {
|
||||
getOrderHashAsync: async (order: Order): Promise<string> => {
|
||||
const orderHash = await devUtilsContract
|
||||
.getOrderHash(order, new BigNumber(order.chainId), order.exchangeAddress)
|
||||
.callAsync();
|
||||
return orderHash;
|
||||
},
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
import { DevUtilsContract } from '@0x/abi-gen-wrappers';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import {
|
||||
ECSignature,
|
||||
@ -16,12 +16,12 @@ import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { assert } from './assert';
|
||||
import { constants } from './constants';
|
||||
import { eip712Utils } from './eip712_utils';
|
||||
import { orderHashUtils } from './order_hash_utils';
|
||||
import { TypedDataError } from './types';
|
||||
|
||||
const devUtilsContract = new DevUtilsContract('0x0000000000000000000000000000000000000000', {
|
||||
isEIP1193: true,
|
||||
} as any);
|
||||
const devUtilsContract = new DevUtilsContract(constants.NULL_ADDRESS, constants.FAKED_PROVIDER as any);
|
||||
|
||||
export const signatureUtils = {
|
||||
/**
|
||||
@ -51,9 +51,7 @@ export const signatureUtils = {
|
||||
if (err.message.includes('User denied message signature')) {
|
||||
throw err;
|
||||
}
|
||||
const orderHash = await devUtilsContract
|
||||
.getOrderHash(order, new BigNumber(order.chainId), order.exchangeAddress)
|
||||
.callAsync();
|
||||
const orderHash = await orderHashUtils.getOrderHashAsync(order);
|
||||
const signatureHex = await signatureUtils.ecSignHashAsync(supportedProvider, orderHash, signerAddress);
|
||||
const signedOrder = {
|
||||
...order,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { DevUtilsContract } from '@0x/abi-gen-wrappers';
|
||||
import { assert } from '@0x/assert';
|
||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
import { Order, SignatureType, ZeroExTransaction } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
@ -10,6 +10,7 @@ import 'mocha';
|
||||
|
||||
import { generatePseudoRandomSalt } from '../src';
|
||||
import { constants } from '../src/constants';
|
||||
import { orderHashUtils } from '../src/order_hash_utils';
|
||||
import { isValidECSignature, signatureUtils } from '../src/signature_utils';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
@ -18,9 +19,7 @@ import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
const devUtilsContract = new DevUtilsContract('0x0000000000000000000000000000000000000000', {
|
||||
isEIP1193: true,
|
||||
} as any);
|
||||
const devUtilsContract = new DevUtilsContract(constants.NULL_ADDRESS, constants.FAKED_PROVIDER as any);
|
||||
|
||||
describe('Signature utils', () => {
|
||||
let makerAddress: string;
|
||||
@ -287,9 +286,7 @@ describe('Signature utils', () => {
|
||||
it('should result in the same signature as signing the order hash without an ethereum message prefix', async () => {
|
||||
// Note: Since order hash is an EIP712 hash the result of a valid EIP712 signature
|
||||
// of order hash is the same as signing the order without the Ethereum Message prefix.
|
||||
const orderHashHex = await devUtilsContract
|
||||
.getOrderHash(order, new BigNumber(order.chainId), order.exchangeAddress)
|
||||
.callAsync();
|
||||
const orderHashHex = await orderHashUtils.getOrderHashAsync(order);
|
||||
const sig = ethUtil.ecsign(
|
||||
ethUtil.toBuffer(orderHashHex),
|
||||
Buffer.from('F2F48EE19680706196E2E339E5DA3491186E0C4C5030670656B0E0164837257D', 'hex'),
|
||||
|
@ -1,26 +1,16 @@
|
||||
import { APIOrder, SignedOrder } from '@0x/connect';
|
||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
const devUtilsContract = new DevUtilsContract('0x0000000000000000000000000000000000000000', {
|
||||
isEIP1193: true,
|
||||
} as any);
|
||||
import { orderHashUtils } from '@0x/order-utils';
|
||||
|
||||
export const utils = {
|
||||
async getOrderHashAsync(order: APIOrder | SignedOrder): Promise<string> {
|
||||
if ((order as APIOrder).metaData) {
|
||||
const apiOrder = order as APIOrder;
|
||||
const orderHash =
|
||||
(apiOrder.metaData as any).orderHash ||
|
||||
(await devUtilsContract
|
||||
.getOrderHash(apiOrder.order, new BigNumber(apiOrder.order.chainId), apiOrder.order.exchangeAddress)
|
||||
.callAsync());
|
||||
(apiOrder.metaData as any).orderHash || (await orderHashUtils.getOrderHashAsync(apiOrder.order));
|
||||
return orderHash;
|
||||
} else {
|
||||
const signedOrder = order as SignedOrder;
|
||||
const orderHash = await devUtilsContract
|
||||
.getOrderHash(signedOrder, new BigNumber(signedOrder.chainId), signedOrder.exchangeAddress)
|
||||
.callAsync();
|
||||
const orderHash = await orderHashUtils.getOrderHashAsync(signedOrder);
|
||||
return orderHash;
|
||||
}
|
||||
},
|
||||
|
@ -1 +1,2 @@
|
||||
export const NULL_BYTES = '0x';
|
||||
export const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
|
@ -8,7 +8,7 @@ export { BigNumber } from './configured_bignumber';
|
||||
export { AbiDecoder } from './abi_decoder';
|
||||
export { logUtils } from './log_utils';
|
||||
export { abiUtils } from './abi_utils';
|
||||
export { NULL_BYTES } from './constants';
|
||||
export { NULL_BYTES, NULL_ADDRESS } from './constants';
|
||||
export { errorUtils } from './error_utils';
|
||||
export { fetchAsync } from './fetch_async';
|
||||
export { signTypedDataUtils } from './sign_typed_data_utils';
|
||||
|
Loading…
x
Reference in New Issue
Block a user