Skip to content

Commit

Permalink
All-2699 Add nft support for Horizen EON (#942)
Browse files Browse the repository at this point in the history
ALL-2699 Add mint support for Horizen EON

Co-authored-by: jiri.andras <jiri.andras@tatum.io>
  • Loading branch information
oliverjantar and jiri.andras authored Sep 26, 2023
1 parent efceb05 commit 39873e8
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 22 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tatumio",
"version": "2.2.35",
"version": "2.2.36",
"license": "MIT",
"repository": "https://github.com/tatumio/tatum-js",
"scripts": {
Expand Down
5 changes: 1 addition & 4 deletions packages/blockchain/eon/src/lib/eon.sdk.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
import { evmBasedSdk } from '@tatumio/shared-blockchain-evm-based'
import { Blockchain } from '@tatumio/shared-core'
import {} from '@tatumio/api-client'
import { abstractSdkNft, SDKArguments } from '@tatumio/shared-abstract-sdk'
import { eonWeb3 } from './services/eon.web3'
import { eonTxService } from './services/eon.tx'

const blockchain = Blockchain.EON

export const TatumEonSDK = (args: SDKArguments, estimateGasFn: (tx: any) => Promise<number>) => {
export const TatumEonSDK = (args: SDKArguments) => {
const web3 = eonWeb3({ blockchain })

const txService = eonTxService({
blockchain,
web3,
estimateGasFn,
})
const evmSdk = evmBasedSdk({ ...args, blockchain, web3 })
const { nft } = abstractSdkNft()

return {
...evmSdk,

nft: {
...txService.erc721,
...nft,
Expand Down
238 changes: 221 additions & 17 deletions packages/blockchain/eon/src/lib/services/eon.tx.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { ChainDeployErc721 } from '@tatumio/shared-blockchain-abstract'
import { SdkErrorCode } from '@tatumio/shared-abstract-sdk'
import {
ChainAddMinterErc721,
ChainBurnErc721,
ChainDeployErc721,
ChainMintErc721,
ChainTransferErc721,
} from '@tatumio/shared-blockchain-abstract'
import {
Erc721Token_Cashback,
Erc721Token_General,
Erc721_Provenance,
EvmBasedSdkError,
EvmBasedWeb3,
evmBasedUtils,
} from '@tatumio/shared-blockchain-evm-based'
import { EvmBasedBlockchain } from '@tatumio/shared-core'
import BigNumber from 'bignumber.js'
import Web3 from 'web3'
import { TransactionConfig } from 'web3-core'

Expand All @@ -15,16 +22,13 @@ const deploySignedTransaction = async ({
web3,
provider,
chainId,
estimateGasFn,
}: {
body: ChainDeployErc721
web3: EvmBasedWeb3
provider?: string
chainId: number
estimateGasFn: (tx: any) => Promise<number>
}) => {
const { fromPrivateKey, fee, name, symbol, nonce, signatureId, publicMint } = body

const client = await web3.getClient(provider, fromPrivateKey)

let abi = Erc721Token_General.abi
Expand All @@ -47,10 +51,179 @@ const deploySignedTransaction = async ({
client,
tx,
web3,
estimateGasFn,
fee.gasLimit,
signatureId,
fromPrivateKey,
fee?.gasPrice,
provider,
)
}

const mintSignedTransaction = async ({
body,
web3,
provider,
chainId,
}: {
body: ChainMintErc721
web3: EvmBasedWeb3
provider?: string
chainId: number
}) => {
const { nonce, signatureId, fee, tokenId, url, fromPrivateKey } = body
const contractAddress = body.contractAddress.trim()
const to = body.to.trim()

const client = web3.getClient(provider, fromPrivateKey)
const contract = new client.eth.Contract(Erc721Token_General.abi as any, contractAddress)

const alreadyMinted = await evmBasedUtils.alreadyMinted(contract, tokenId)
if (alreadyMinted) {
throw new EvmBasedSdkError({ code: SdkErrorCode.EVM_ERC721_CANNOT_PREPARE_MINT_ALREADY_MINTED })
}

if (contractAddress) {
const tx: TransactionConfig = {
from: 0,
to: contractAddress,
data: contract.methods.mintWithTokenURI(to, tokenId, url).encodeABI(),
nonce: nonce,
chainId,
}

return prepareSignedTransactionAbstraction(
client,
tx,
web3,
fee.gasLimit,
signatureId,
fromPrivateKey,
fee?.gasPrice,
provider,
)
}
throw new Error('Contract address should not be empty')
}

const burnSignedTransaction = async ({
body,
web3,
provider,
chainId,
}: {
body: ChainBurnErc721
web3: EvmBasedWeb3
provider?: string
chainId: number
}) => {
const { fromPrivateKey, tokenId, fee, nonce, signatureId } = body
const contractAddress = body.contractAddress?.trim()

const client = web3.getClient(provider, fromPrivateKey)

const contract = new client.eth.Contract(Erc721Token_General.abi as any, contractAddress)
const tx: TransactionConfig = {
from: 0,
to: contractAddress,
data: contract.methods.burn(tokenId).encodeABI(),
nonce,
chainId,
}

return prepareSignedTransactionAbstraction(
client,
tx,
web3,
fee.gasLimit,
signatureId,
fromPrivateKey,
fee?.gasPrice,
provider,
)
}

const addMinterSignedTransaction = async ({
body,
web3,
provider,
chainId,
}: {
body: ChainAddMinterErc721
web3: EvmBasedWeb3
provider?: string
chainId: number
}) => {
const { fromPrivateKey, fee, nonce, signatureId } = body
const contractAddress = body.contractAddress?.trim()
const minter = body.minter?.trim()

const client = web3.getClient(provider, fromPrivateKey)

const contract = new client.eth.Contract(Erc721Token_General.abi as any, contractAddress)
const tx: TransactionConfig = {
from: 0,
to: contractAddress,
data: contract.methods
.grantRole('0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6', minter)
.encodeABI(),
nonce,
chainId,
}

return prepareSignedTransactionAbstraction(
client,
tx,
web3,
fee?.gasLimit,
signatureId,
fromPrivateKey,
fee?.gasPrice,
provider,
)
}

const transferSignedTransaction = async ({
body,
web3,
provider,
chainId,
}: {
body: ChainTransferErc721
web3: EvmBasedWeb3
provider?: string
chainId: number
}) => {
const { fromPrivateKey, tokenId, fee, nonce, signatureId, value, provenance, provenanceData, tokenPrice } =
body
const contractAddress = body.contractAddress?.trim()
const to = body.to?.trim()

const client = await web3.getClient(provider, fromPrivateKey)

const contract = new client.eth.Contract(Erc721Token_General.abi as any, contractAddress)
const dataBytes = provenance
? Buffer.from(provenanceData + "'''###'''" + client.utils.toWei(tokenPrice!, 'ether'), 'utf8')
: ''
const tokenData = provenance
? contract.methods.safeTransfer(to, tokenId, `0x${dataBytes.toString('hex')}`).encodeABI()
: contract.methods.safeTransfer(to, tokenId).encodeABI()

const tx: TransactionConfig = {
from: 0,
to: contractAddress,
data: tokenData,
nonce,
value: value ? `0x${new BigNumber(value).multipliedBy(1e18).toString(16)}` : undefined,
chainId,
}

return prepareSignedTransactionAbstraction(
client,
tx,
web3,
fee.gasLimit,
signatureId,
fromPrivateKey,
fee?.gasPrice,
provider,
)
Expand All @@ -60,10 +233,9 @@ const prepareSignedTransactionAbstraction = async (
client: Web3,
transaction: TransactionConfig,
web3: EvmBasedWeb3,
estimateGasFn: (tx: any) => Promise<number>,
gasLimit: string,
signatureId?: string,
fromPrivateKey?: string,
gasLimit?: string,
gasPrice?: string,
provider?: string,
) => {
Expand All @@ -83,8 +255,6 @@ const prepareSignedTransactionAbstraction = async (

tx.from = tx.from || client.eth.defaultAccount || 0

tx.gas = tx.gas ?? (await estimateGasFn(tx))

if (!fromPrivateKey) {
throw new Error('signatureId or fromPrivateKey has to be defined')
}
Expand All @@ -100,22 +270,56 @@ const prepareSignedTransactionAbstraction = async (
return signedTransaction.rawTransaction
}

export const eonTxService = (args: {
blockchain: EvmBasedBlockchain
web3: EvmBasedWeb3
estimateGasFn: (tx: any) => Promise<number>
}) => {
export const eonTxService = (args: { blockchain: EvmBasedBlockchain; web3: EvmBasedWeb3 }) => {
return {
erc721: {
prepare: {
/**
* Sign deploy ERC 721 transaction with private keys locally. Nothing is broadcast to the blockchain.
* @param body content of the transaction to broadcast
* @param provider url of the Server to connect to. If not set, default public server will be used.
* @returns transaction data to be broadcast to blockchain.
*/
deploySignedTransaction: async (body: ChainDeployErc721, chainId: number, provider?: string) =>
deploySignedTransaction({
body,
web3: args.web3,
provider,
chainId,
estimateGasFn: args.estimateGasFn,
}),
/**
* Sign mint ERC 721 transaction with private keys locally. Nothing is broadcast to the blockchain.
* @param body content of the transaction to broadcast
* @param provider url of the Server to connect to. If not set, default public server will be used.
* @returns transaction data to be broadcast to blockchain.
*/
mintSignedTransaction: async (body: ChainMintErc721, chainId: number, provider?: string) =>
mintSignedTransaction({ body, web3: args.web3, provider, chainId }),
/**
* Sign burn ERC 721 transaction with private keys locally. Nothing is broadcast to the blockchain.
* @param body content of the transaction to broadcast
* @param provider url of the Server to connect to. If not set, default public server will be used.
* @returns transaction data to be broadcast to blockchain.
*/
burnSignedTransaction: async (body: ChainBurnErc721, chainId: number, provider?: string) =>
burnSignedTransaction({ body, web3: args.web3, provider, chainId }),
/**
* Sign transfer ERC 721 transaction with private keys locally. Nothing is broadcast to the blockchain.
* @param body content of the transaction to broadcast
* @param provider url of the Server to connect to. If not set, default public server will be used.
* @returns transaction data to be broadcast to blockchain.
*/
transferSignedTransaction: async (body: ChainTransferErc721, chainId: number, provider?: string) =>
transferSignedTransaction({ body, web3: args.web3, provider, chainId }),

/**
* Sign add minter to ERC 721 with private keys locally. Nothing is broadcast to the blockchain.
* @param body content of the transaction to broadcast
* @param provider url of the Server to connect to. If not set, default public server will be used.
* @returns transaction data to be broadcast to blockchain.
*/
addMinterSignedTransaction: (body: ChainAddMinterErc721, chainId: number, provider: string) =>
addMinterSignedTransaction({ body, web3: args.web3, provider, chainId }),
},
},
}
Expand Down

0 comments on commit 39873e8

Please sign in to comment.