Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate to ethers #76

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,6 @@ module.exports.BLOCKCHAINS = {
},
};

module.exports.WEBSOCKET_PROVIDER_OPTIONS = {
reconnect: {
auto: true,
delay: 1000, // ms
maxAttempts: 3,
},
clientConfig: {
keepalive: true,
keepaliveInterval: 30 * 1000, // ms
},
};

module.exports.OPERATIONS = {
PUBLISH: 'publish',
GET: 'get',
Expand Down
2 changes: 1 addition & 1 deletion dist/dkg.min.js

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions dist/dkg.min.js.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/*!
* Copyright (c) 2016-2021 Digital Bazaar, Inc. All rights reserved.
zeroxbt marked this conversation as resolved.
Show resolved Hide resolved
*/

/*!
* Copyright (c) 2016-2022 Digital Bazaar, Inc. All rights reserved.
*/

/*!
* The buffer module from node.js, for the browser.
*
Expand Down
2 changes: 1 addition & 1 deletion examples/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ function divider() {

divider();

let getLatestAssetResult = await DkgClient.asset.get(createAssetResult.UAL);
const getLatestAssetResult = await DkgClient.asset.get(createAssetResult.UAL);
console.log('======================== ASSET LATEST RESOLVED');
console.log(JSON.stringify(getLatestAssetResult, null, 2));

Expand Down
2 changes: 1 addition & 1 deletion managers/asset-operations-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ class AssetOperationsManager {
);
return {
UAL,
publicAssertionId: publicAssertionId,
publicAssertionId,
operation: getOperationStatusObject(operationResult, operationId),
};
}
Expand Down
12,156 changes: 5,121 additions & 7,035 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,20 @@
"dependencies": {
"assertion-tools": "^2.0.2",
"axios": "^0.27.2",
"crypto-browserify": "^3.12.0",
"dkg-evm-module": "^4.0.4",
"ethers": "^6.1.0",
"https-browserify": "^1.0.0",
"jsonld": "^8.1.0",
"web3": "^1.7.3"
"process": "^0.11.10",
"stream-browserify": "^3.0.0",
"stream-http": "^3.2.0"
},
"devDependencies": {
"crypto-browserify": "^3.12.0",
"eslint": "^8.23.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^8.5.0",
"https-browserify": "^1.0.0",
"prettier": "^2.7.1",
"stream-browserify": "^3.0.0",
"stream-http": "^3.2.0",
"terser-webpack-plugin": "^5.3.6",
"webpack": "^5.75.0",
"webpack-cli": "^4.9.2"
Expand Down
96 changes: 57 additions & 39 deletions services/blockchain-service/blockchain-service-base.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const Web3 = require('web3');
const ethers = require('ethers');
const AssertionStorageAbi = require('dkg-evm-module/abi/AssertionStorage.json');
const HubAbi = require('dkg-evm-module/abi/Hub.json');
const ServiceAgreementV1Abi = require('dkg-evm-module/abi/ServiceAgreementV1.json');
Expand All @@ -15,7 +15,9 @@ const FIXED_GAS_LIMIT_METHODS = {
};

class BlockchainServiceBase {
constructor() {
constructor(config) {
this.config = config;
this.events = {};
this.abis = {};
this.abis.AssertionStorage = AssertionStorageAbi;
this.abis.Hub = HubAbi;
Expand All @@ -25,50 +27,62 @@ class BlockchainServiceBase {
this.abis.UnfinalizedStateStorage = UnfinalizedStateStorageAbi;
this.abis.ContentAsset = ContentAssetAbi;
this.abis.Token = TokenAbi;

this.abis.ContentAsset.filter((obj) => obj.type === 'event').forEach((event) => {
const concatInputs = event.inputs.map((input) => input.internalType).join(',');

this.events[event.name] = {
hash: ethers.id(`${event.name}(${concatInputs})`),
inputs: event.inputs,
};
});
}

initializeWeb3() {
initializeProvider() {
// overridden by subclasses
return {};
}

async decodeEventLogs() {
// overridden by subclasses
return {};
async decodeEventLogs(receipt, eventName) {
let result;
const { hash } = this.events[eventName];

const iface = new ethers.Interface(this.abis.ContentAsset);

receipt.logs.forEach((row) => {
if (row.topics[0] === hash) {
const parsedLog = iface.parseLog({ data: row.data, topics: row.topics });

result = parsedLog.args;
}
});
return result;
}

async callContractFunction(contractName, functionName, args, blockchain) {
const contractInstance = await this.getContractInstance(contractName, blockchain);
return contractInstance.methods[functionName](...args).call();
return contractInstance[functionName](...args);
}

async prepareTransaction(contractInstance, functionName, args, blockchain) {
const web3Instance = await this.getWeb3Instance(blockchain);
async getTransactionOptions(contractInstance, functionName, args, blockchain) {
const provider = await this.getProvider(blockchain);
let gasLimit;
if (FIXED_GAS_LIMIT_METHODS[functionName]) {
gasLimit = FIXED_GAS_LIMIT_METHODS[functionName];
gasLimit = BigInt(FIXED_GAS_LIMIT_METHODS[functionName]);
} else {
gasLimit = await contractInstance.methods[functionName](...args).estimateGas({
from: blockchain.publicKey,
});
gasLimit = await contractInstance.getFunction(functionName).estimateGas(...args);
}

const encodedABI = await contractInstance.methods[functionName](...args).encodeABI();

let gasPrice;

if (blockchain.name.startsWith('otp')) {
gasPrice = await web3Instance.eth.getGasPrice();
gasPrice = (await provider.getFeeData()).gasPrice;
} else {
gasPrice = Web3.utils.toWei('100', 'Gwei');
gasPrice = this.convertToWei(100, 'gwei');
}

return {
from: blockchain.publicKey,
to: contractInstance.options.address,
data: encodedABI,
gasPrice,
gas: gasLimit,
gasLimit,
};
}

Expand All @@ -85,13 +99,13 @@ class BlockchainServiceBase {
}
}

async getWeb3Instance(blockchain) {
async getProvider(blockchain) {
this.ensureBlockchainInfo(blockchain);
if (!this[blockchain.name].web3) {
this.initializeWeb3(blockchain.name, blockchain.rpc);
if (!this[blockchain.name].provider) {
this.initializeProvider(blockchain.name, blockchain.rpc);
}

return this[blockchain.name].web3;
return this[blockchain.name].provider;
}

async getContractAddress(contractName, blockchain) {
Expand All @@ -100,9 +114,12 @@ class BlockchainServiceBase {
this[blockchain.name].contracts[blockchain.hubContract] = {};
}
if (!this[blockchain.name].contracts[blockchain.hubContract].Hub) {
const web3Instance = await this.getWeb3Instance(blockchain);
this[blockchain.name].contracts[blockchain.hubContract].Hub =
new web3Instance.eth.Contract(this.abis.Hub, blockchain.hubContract);
const provider = await this.getProvider(blockchain);
this[blockchain.name].contracts[blockchain.hubContract].Hub = new ethers.Contract(
blockchain.hubContract,
this.abis.Hub,
provider,
);
}

if (!this[blockchain.name].contractAddresses[blockchain.hubContract][contractName]) {
Expand All @@ -126,11 +143,12 @@ class BlockchainServiceBase {
await this.getContractAddress(contractName, blockchain);
}
if (!this[blockchain.name].contracts[blockchain.hubContract][contractName]) {
const web3Instance = await this.getWeb3Instance(blockchain);
const provider = await this.getProvider(blockchain);
this[blockchain.name].contracts[blockchain.hubContract][contractName] =
new web3Instance.eth.Contract(
this.abis[contractName],
new ethers.Contract(
this[blockchain.name].contractAddresses[blockchain.hubContract][contractName],
this.abis[contractName],
provider,
);
}

Expand All @@ -150,7 +168,7 @@ class BlockchainServiceBase {
blockchain,
);

let tokensNeeded = BigInt(requestData.tokenAmount) - BigInt(allowance);
const tokensNeeded = BigInt(requestData.tokenAmount) - BigInt(allowance);

if (tokensNeeded > 0) {
await this.executeContractFunction(
Expand Down Expand Up @@ -217,7 +235,7 @@ class BlockchainServiceBase {
blockchain,
);

let tokensNeeded = BigInt(tokenAmount) - BigInt(allowance);
const tokensNeeded = BigInt(tokenAmount) - BigInt(allowance);

if (tokensNeeded > 0) {
await this.executeContractFunction(
Expand Down Expand Up @@ -437,14 +455,14 @@ class BlockchainServiceBase {
}

async getLatestBlock(blockchain) {
const web3 = await this.getWeb3Instance(blockchain);
const blockNumber = await web3.eth.getBlockNumber();
const provider = await this.getProvider(blockchain);
const blockNumber = await provider.getBlockNumber();

return web3.eth.getBlock(blockNumber);
return provider.getBlock(blockNumber);
}

convertToWei(ether) {
return Web3.utils.toWei(ether.toString(), 'ether');
convertToWei(value, fromUnit = 'ether') {
return ethers.parseUnits(value.toString(), fromUnit).toString();
}
}
module.exports = BlockchainServiceBase;
Original file line number Diff line number Diff line change
@@ -1,63 +1,44 @@
const Web3 = require('web3');
const ethers = require('ethers');
const BlockchainServiceBase = require('../blockchain-service-base.js');
const { WEBSOCKET_PROVIDER_OPTIONS } = require('../../../constants.js');

class BrowserBlockchainService extends BlockchainServiceBase {
constructor(config = {}) {
super(config);
this.config = config;
}

initializeWeb3(blockchainName, blockchainRpc) {
initializeProvider(blockchainName, blockchainRpc) {
if (typeof window.Web3 === 'undefined' || !window.Web3) {
this.logger.error(
'No web3 implementation injected, please inject your own Web3 implementation.',
);
return;
}
if (window.ethereum) {
this[blockchainName].web3 = new window.Web3(window.ethereum);
if (typeof window.ethereum !== 'undefined') {
this[blockchainName].provider = new ethers.Web3Provider(window.ethereum);
} else if (blockchainRpc.startsWith('ws')) {
const provider = new window.Web3.providers.WebsocketProvider(
blockchainRpc,
WEBSOCKET_PROVIDER_OPTIONS,
);
this[blockchainName].web3 = new Web3(provider);
this[blockchainName].provider = new ethers.WebSocketProvider(blockchainRpc);
} else {
this[blockchainName].web3 = new window.Web3(blockchainRpc);
this[blockchainName].provider = new ethers.JsonRpcProvider(blockchainRpc);
}
}

async executeContractFunction(contractName, functionName, args, blockchain) {
const contractInstance = await this.getContractInstance(contractName, blockchain);
const tx = await this.prepareTransaction(contractInstance, functionName, args, {
const options = await this.getTransactionOptions(contractInstance, functionName, args, {
name: blockchain.name,
publicKey: await this.getAccount(),
});

return contractInstance.methods[functionName](...args).send(tx);
return contractInstance[functionName](...args, options);
}

async getAccount() {
if (!this.account) {
if (!window.ethereum) {
throw Error('This operation can be performed only by using Metamask accounts.');
}
const accounts = await window.ethereum
.request({
method: 'eth_requestAccounts',
})
.catch(() => this.logger.error('There was an error fetching your accounts'));

[this.account] = accounts;
const signer = this.provider.getSigner();
this.account = await signer.getAddress();
}
return this.account;
}

async decodeEventLogs(receipt, eventName) {
return receipt.events[eventName].returnValues;
}

async transferAsset(tokenId, to, blockchain) {
return this.executeContractFunction(
'ContentAssetStorage',
Expand Down
Loading