Sample code and reference architecture to deploy an NFT on the Ethereum blockchain using Amazon Managed Blockchain
Deploy NFT on Ethereum using Amazon Managed Blockchain
This repository contains sample code to deploy ERC-721 smart contracts on the Ethereum blockchain network using Amazon Managed Blockchain as a geth node. It provides a reference architecture for deploying a contract, minting NFT tokens and querying token owners using serverless components
The repo is structured as follows:
bash
.
โโโ CODEOFCONDUCT.md
โโโ CONTRIBUTING.md
โโโ LICENSE
โโโ README.md
โโโ images
โโโ serverless</code></pre>
Reference architecture

Pre-requisites
1. An AWS account with a VPC and a public subnet. Ensure you have permissions to make objects in the S3 bucket public 2. AWS SAM CLI : Install the AWS SAM CLI. 3. Node.js: Install Node.js 14, including the npm package management tool. 4. Docker: Install Docker community edition.
Deploy Ethereum node and Serverless components
An AWS Serverless Application Model (SAM) template is used to deploy the stack
bash
cd serverless/
sam build
.... Building codeuri: /Users/pravincv/Nft-amb-repo/serverless/lambdas/nftmain runtime: nodejs14.x metadata: {} architecture: x86_64 functions: ['nftmain'] Running NodejsNpmBuilder:NpmPack Running NodejsNpmBuilder:CopyNpmrc Running NodejsNpmBuilder:CopySource Running NodejsNpmBuilder:NpmInstall Running NodejsNpmBuilder:CleanUpNpmrc
Build Succeeded</code></pre>
On success completion of the build, deploy the stack
bash
sam deploy --guided --capabilities CAPABILITYNAMEDIAM</code></pre>
Input the parameter values and confirm changes to deploy
Stack Name [nft-stack]: AWS Region [ap-southeast-1]: - region where Amazon Managed Blockchain is supported Parameter pEmail [name@example.com]: - email id that will receive Amazon SNS notifications Parameter pSubnetId [subnet-xxxxxxx]: - public subnet where the AWS Fargate task will run Parameter pNftBucketName [nftmetadata]: - bucket where NFT metadata will be stored Parameter pConfirmationBlocks [50]: - number of confirmations on the blockchain, to wait for Parameter pClusterName [nftcluster]: - AWS ECS cluster name Parameter pContainerName [rinkeby]: - name of container Parameter pRepositoryName [nftrepository]: - AWS ECR where the Docker images will be stored Parameter pIpRangeWhitelist [.../**]: - IP address CIDR that is allowed to invoke the API Parameter pNetworkId [n-ethereum-rinkeby]: - default network is rinkeby. Can choose ropsten if desired Parameter pInstanceType [bc.t3.large]: - choose desired instance size Parameter pAvailabilityZone [ap-southeast-1a]: - choose availability zone based on region Confirm changes before deploy [Y/n]: - confirm changes Y #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: - choose Y Save arguments to configuration file [Y/n]: -choose Y SAM configuration file [samconfig.toml]: - default file to save the samconfig SAM configuration environment [default]:
The following resources are created on deployment

This creates the following resources
- nftmain - AWS Lambda function that provides APIs to deploy an ERC-721 contract to the Ethereum rinkeby test network, mint a new token as well get the owner of a specified token minted. The deploy API sends out an SNS message on successful deployment of a contract
* invokeFargateTask - This Lambda function is triggered by the AWS SNS message sent by the nftmain Lambda. On being triggered, it invokes a task that awaits until the rinkeby blockchain has confirmed the deployment confirmationBlocks (passed as an environment variable) number of times
* ethTxnTopic - Amazon SNS topic to which nftmain Lambda published the transaction id on deployment of a contract
* ethConfirmationTopic - Amazon SNS topic to which the task publishes a message on completing confirmationBlocks number of confirmations on the Rinkeby network
* cluster and taskDefinition - cluster and task definition that provides the compute for the 'confirmation' logic
* nftapi - api created and exposed via the api gateway for users to invoke HTTP POST
* ecrRepository - repository where the docker image for the task is stored
To complete the serverless stack, create a Docker image and push to the ecrRepository by building, tagging and pushing the image as below.
bash
cd serverless/
- aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <account id>.dkr.ecr.<region>.amazonaws.com
- docker build -t nftrepository .
- docker tag nftrepository:latest <account>.dkr.ecr.<region><.amazonaws.com/nftrepository:latest
- docker push <account>.dkr.ecr.<region>.amazonaws.com/nftrepository:latest</code></pre>
To create a transaction on the Ethereum Rinkeby network, a private-public key pair is required. Generate the private key and upload to AWS SSM Parameter Store as an encrypted string as 'ethSystemKey'. - ensure the string excludes the first 2 characters, 0x of the privatekey . Add some ethereum test tokens for the rinkeby network by entering the public key https://faucets.chain.link/rinkeby and requesting ethereum test tokens. Please note that for AWS SSM Paramter Store might not be sufficient for some cases where wallets bear real funds.
Deploying a test contract, minting an NFT and checking token ownership
Now we are ready to deploy an ERC-721 smart contract to the network.
bash
โโโ nftmain โย ย โโโ NFTSamples โย ย โย ย โโโ build โย ย โย ย โย ย โโโ NFT_BaseURI.json โย ย โย ย โโโ contracts โย ย โย ย โโโ NFTSample.sol โย ย โย ย โโโ NFT_BaseURI.sol โย ย โโโ aws-web3-http-provider.js โย ย โโโ deploy_contract.js โย ย โโโ get_owner.js โย ย โโโ index.js โย ย โโโ mint_nft.js โย ย โโโ package-lock.json โโโ package.json โโโ utils.js โโโ txconfirmation โโโ index.js</code></pre>
The contract to be deployed is stored in the nftmain directory under NFTSamples. We'll be using curl -X POST to deploy and mint the NFT. Obtain the API endpoint i.e InvokeURL from Amazon API Gateway ->APIs > Stages on the AWS Console. bash cd serverless/test-events
serverless/test-events โโโ deploy.json โโโ getowner.json โโโ mint.json</code></pre>
Edit the deploy.json file to fill up the needed values.
bash
> cat deploy.json
{"requestType": "deploy", "tokenName": "coolnft", # name of nft "tokenTicker": "SYMB", # symbol "metadataFilename": "metadata.json", # name of metadata file "metadata":{ #metadata associated with nft "description": "useful description", "image": "<url of the image, preferably an IPFS hash>", "name": " coolnft" }} > curl -X POST https://<api> .execute-api.<region>.amazonaws.com/nftapi -H "Content-Type: application/json" -d @deploy.json</code></pre>
The deploy command returns a transaction id hash and the contract address.
bash
{"Transaction id":"0x6b2af81c34055b678e5a8ae401f508fcbf950341df7e55e7372e80f75faf8afc","ContractAddress":"0x8A3Ce65B266E8DE37Fe7d2e4911CA4578B5a7445"
> cat mint.json {"requestType": "mint", "contractAddress": "0x8A3Ce65B266E8DE37Fe7d2e4911CA4578B5a7445", -> address of the contract address of the deployed contract "mintAddress": "0x905b8699E611a5F1f74BF5Cc3cCa2aCd175ec0c0" -> public key of any another wallet/address } > curl -X POST https://<api>.execute-api.<region>.amazonaws.com/nftapi -H "Content-Type: application/json" -d @mint.json</code></pre>
The response contains the transaction id ash
bash
{"Mint Tx Hash":"0x960080892462ea76a90a5a00fe88ebc5d85d0b84d75e781ca5aa14e5829a0a14"}
> cat getowner.json
{"requestType": "mint",
"contractAddress": "0x8A3Ce65B266E8DE37Fe7d2e4911CA4578B5a7445", -> address of the contract address of the deployed contract
"tokenID": "0" -> ID of the token that was minted previously
}
> curl -X POST https://<api>.<region>.amazonaws.com/nftapi -H "Content-Type: application/json" -d @getowner.json</code></pre>
The response provides the address of the owner for whom the token was minted. bash {"Owner address":"0x905b8699E611a5F1f74BF5Cc3cCa2aCd175ec0c0"}</code></pre>
Security
See CONTRIBUTING for more information.
License
This library is licensed under the MIT-0 License. See the LICENSE file.