@0xpolygonid/js-sdk
Version:
SDK to work with Polygon ID
194 lines (193 loc) • 8.76 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EthStateStorage = exports.defaultEthConnectionConfig = void 0;
const ethers_1 = require("ethers");
const circuits_1 = require("../../circuits");
const utils_1 = require("../../utils");
const State_json_1 = __importDefault(require("./abi/State.json"));
const js_iden3_core_1 = require("@iden3/js-iden3-core");
const blockchain_1 = require("../../blockchain");
const common_1 = require("./common");
exports.defaultEthConnectionConfig = {
url: 'http://localhost:8545',
defaultGasLimit: 600000,
minGasPrice: '0',
maxGasPrice: '100000000000',
confirmationBlockCount: 5,
confirmationTimeout: 600000,
contractAddress: '',
receiptTimeout: 600000,
rpcResponseTimeout: 5000,
waitReceiptCycleTime: 30000,
waitBlockCycleTime: 3000
};
/**
*
*
* @public
* @class EthStateStorage
* @implements implements IStateStorage interface
*/
class EthStateStorage {
/**
* Creates an instance of EthStateStorage.
* @param {EthConnectionConfig} [ethConfig=defaultEthConnectionConfig]
*/
constructor(ethConfig) {
this.ethConfig = ethConfig;
const config = Array.isArray(ethConfig) ? ethConfig[0] : ethConfig;
this.provider = new ethers_1.JsonRpcProvider(config.url);
this.stateContract = new ethers_1.Contract(config.contractAddress, State_json_1.default, this.provider);
this._transactionService = new blockchain_1.TransactionService(this.getRpcProvider());
}
/** {@inheritdoc IStateStorage.getLatestStateById} */
async getLatestStateById(id) {
const { stateContract } = this.getStateContractAndProviderForId(id);
const rawData = await stateContract.getStateInfoById(id);
const stateInfo = {
id: BigInt(rawData[0]),
state: BigInt(rawData[1]),
replacedByState: BigInt(rawData[2]),
createdAtTimestamp: BigInt(rawData[3]),
replacedAtTimestamp: BigInt(rawData[4]),
createdAtBlock: BigInt(rawData[5]),
replacedAtBlock: BigInt(rawData[6])
};
return stateInfo;
}
/** {@inheritdoc IStateStorage.getStateInfoByIdAndState} */
async getStateInfoByIdAndState(id, state) {
const { stateContract } = this.getStateContractAndProviderForId(id);
const rawData = await stateContract.getStateInfoByIdAndState(id, state);
const stateInfo = {
id: BigInt(rawData[0]),
state: BigInt(rawData[1]),
replacedByState: BigInt(rawData[2]),
createdAtTimestamp: BigInt(rawData[3]),
replacedAtTimestamp: BigInt(rawData[4]),
createdAtBlock: BigInt(rawData[5]),
replacedAtBlock: BigInt(rawData[6])
};
return stateInfo;
}
/** {@inheritdoc IStateStorage.publishState} */
async publishState(proof, signer) {
const stateTransitionPubSig = new circuits_1.StateTransitionPubSignals();
stateTransitionPubSig.pubSignalsUnmarshal(utils_1.byteEncoder.encode(JSON.stringify(proof.pub_signals)));
const { userId, oldUserState, newUserState, isOldStateGenesis } = stateTransitionPubSig;
const { stateContract, provider } = this.getStateContractAndProviderForId(userId.bigInt());
const contract = stateContract.connect(signer);
const preparedZkpProof = (0, common_1.prepareZkpProof)(proof.proof);
const payload = [
userId.bigInt().toString(),
oldUserState.bigInt().toString(),
newUserState.bigInt().toString(),
isOldStateGenesis,
preparedZkpProof.a,
preparedZkpProof.b,
preparedZkpProof.c
];
const feeData = await provider.getFeeData();
const maxFeePerGas = exports.defaultEthConnectionConfig.maxFeePerGas
? BigInt(exports.defaultEthConnectionConfig.maxFeePerGas)
: feeData.maxFeePerGas;
const maxPriorityFeePerGas = exports.defaultEthConnectionConfig.maxPriorityFeePerGas
? BigInt(exports.defaultEthConnectionConfig.maxPriorityFeePerGas)
: feeData.maxPriorityFeePerGas;
const gasLimit = await contract.transitState.estimateGas(...payload);
const txData = await contract.transitState.populateTransaction(...payload);
const request = {
to: txData.to,
data: txData.data,
gasLimit,
maxFeePerGas,
maxPriorityFeePerGas
};
const { txnHash } = await this._transactionService.sendTransactionRequest(signer, request);
return txnHash;
}
/** {@inheritdoc IStateStorage.publishStateGeneric} */
async publishStateGeneric(signer, userStateTransitionInfo) {
const { userId, oldUserState, newUserState, isOldStateGenesis, methodId, methodParams } = userStateTransitionInfo;
const { stateContract, provider } = this.getStateContractAndProviderForId(userId.bigInt());
const contract = stateContract.connect(signer);
const feeData = await provider.getFeeData();
const maxFeePerGas = exports.defaultEthConnectionConfig.maxFeePerGas
? BigInt(exports.defaultEthConnectionConfig.maxFeePerGas)
: feeData.maxFeePerGas;
const maxPriorityFeePerGas = exports.defaultEthConnectionConfig.maxPriorityFeePerGas
? BigInt(exports.defaultEthConnectionConfig.maxPriorityFeePerGas)
: feeData.maxPriorityFeePerGas;
const payload = [
userId.bigInt().toString(),
oldUserState.bigInt().toString(),
newUserState.bigInt().toString(),
isOldStateGenesis,
methodId,
methodParams //'0x'
];
const gasLimit = await contract.transitStateGeneric.estimateGas(...payload);
const txData = await contract.transitStateGeneric.populateTransaction(...payload);
const request = {
to: txData.to,
data: txData.data,
gasLimit,
maxFeePerGas,
maxPriorityFeePerGas
};
const { txnHash } = await this._transactionService.sendTransactionRequest(signer, request);
return txnHash;
}
/** {@inheritdoc IStateStorage.getGISTProof} */
async getGISTProof(id) {
const { stateContract } = this.getStateContractAndProviderForId(id);
const data = await stateContract.getGISTProof(id);
return {
root: BigInt(data.root.toString()),
existence: data.existence,
siblings: data.siblings?.map((sibling) => BigInt(sibling.toString())),
index: BigInt(data.index.toString()),
value: BigInt(data.value.toString()),
auxExistence: data.auxExistence,
auxIndex: BigInt(data.auxIndex.toString()),
auxValue: BigInt(data.auxValue.toString())
};
}
/** {@inheritdoc IStateStorage.getGISTRootInfo} */
async getGISTRootInfo(root, id) {
const { stateContract } = this.getStateContractAndProviderForId(id);
const data = await stateContract.getGISTRootInfo(root);
return {
root: BigInt(data.root.toString()),
replacedByRoot: BigInt(data.replacedByRoot.toString()),
createdAtTimestamp: BigInt(data.createdAtTimestamp.toString()),
replacedAtTimestamp: BigInt(data.replacedAtTimestamp.toString()),
createdAtBlock: BigInt(data.createdAtBlock.toString()),
replacedAtBlock: BigInt(data.replacedAtBlock.toString())
};
}
/** {@inheritdoc IStateStorage.getRpcProvider} */
getRpcProvider() {
return this.provider;
}
getStateContractAndProviderForId(id) {
const idTyped = js_iden3_core_1.Id.fromBigInt(id);
const chainId = (0, js_iden3_core_1.getChainId)(js_iden3_core_1.DID.blockchainFromId(idTyped), js_iden3_core_1.DID.networkIdFromId(idTyped));
const config = this.networkByChainId(chainId);
const provider = new ethers_1.JsonRpcProvider(config.url);
const stateContract = new ethers_1.Contract(config.contractAddress, State_json_1.default, provider);
return { stateContract, provider };
}
networkByChainId(chainId) {
const config = Array.isArray(this.ethConfig) ? this.ethConfig : [this.ethConfig];
const network = config.find((c) => c.chainId === chainId);
if (!network) {
throw new Error(`chainId "${chainId}" not supported`);
}
return network;
}
}
exports.EthStateStorage = EthStateStorage;