This app is intended to link KONG HaLo and SiLo devices that are registered in KONG registry with IPFS resources and smart contracts in order to create gaslessly minted crypto assets tied to HaLo's and SiLo's. The legacy portion of the server consists of an ExpressJS app communicating with a MongoDB database. This database mirrors the SiLo device information registered in the KONG registry contract and associated IPFS documents, e.g. the primary public key of a given device.
The new minting process leverages Arweave to create records in a fully decentralized fashion that do not rely on this server after creation. This process is currently only available to HaLo devices via the /mint endpoint.
This app consists of three kinds of interfaces: those relating directly to Devices, those relating to Tokens associated with devices and those used to Reveal token information for devices. Device interfaces are typically low level and can be considered to be "offchain" or unminted.
GET /device : find a SiLo device.Present x and y public key coordinates as quert parameters in a GET request to look up the information of a registered device.
curl --location --request GET 'localhost:3000/device?x=1f8b3a5703b376d9b82869605866a3d8bc4e08803873eba4a4c5e6ee847aae28&y=14a12a78c29acd8b2748f19a96c725111c873bf06e7514b042aa7ed1be718730'
A successful retrieval of the device will return all information in the database relating to the device:
{
"_id": "6095a4267cbf072c0888ed60",
"hardwareHash": "0x3d83f849819dddb68c5f464f6d1e8e6e9876d1c4236287db1ee5fdba2f9b9fe3",
"primaryPublicKeyHash": "0xe2e592b208029d63e9fb7fd00690a1a5331c125ea222e14335d78a79792fcbc9",
"root": "0x6972388f34d8c7576f936f103728f7d2820224ec29d136bd1ad881c950f8e72b",
"arweave": "9rFJMb1JflwadEzOvC_GOWdVxL6A8A2nOnL01g3APVk",
"cid": "QmbHnwBuM7Y41Q1DqnMDRx8yQ1aCMtqVka9biPY6cjWogq"
}
Required
x parameter should match the X coordinate of the device's primary P256 public key.y parameter should match the Y coordinate of the device's primary P256 public key.POST /link : link media to a SiLo device.Post a recent signature along with an IPFS document (e.g. image) that you wish to associate with the device. A minter address can also be included or set to 0 as shown in the example here. NOTE: this process is currently centralized to this server.
curl --location --request POST 'localhost:3000/link' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'x=a1441c4e7dabb340fff0b27d26f9c0c44687a84d02a8217d7594185ccddfb06b' \
--data-urlencode 'y=4f0d74de943e68de5ab6499e9d81058aa55c86fef20dde1ba32a073b5f805ebd' \
--data-urlencode 'r=58d0990422a4acd64eb5c9016561cf4e3ae01869f1582dd6b5aa46ae81222cdc' \
--data-urlencode 's=e4052861cb46683a4da0ac8211b2a778b38c9489d334979b9a80b720f2fca715' \
--data-urlencode 'blockNumber=12421117' \
--data-urlencode 'address=0000000000000000000000000000000000000000' \
--data-urlencode 'cid=QmbHnwBuM7Y41Q1DqnMDRx8yQ1aCMtqVka9biPY6cjWogq'
--data-urlencode 'name=NFT'
--data-urlencode 'description=Chipped'
If the CID is successfully added, the server will indicate that in the result:
cid set to QmbHnwBuM7Y41Q1DqnMDRx8yQ1aCMtqVka9biPY6cjWogq
Required
x parameter should match the X coordinate of the device's primary P256 public key.y parameter should match the Y coordinate of the device's primary P256 public key.r parameter corresponding to the R integer of the signature.s parameter corresponding to the S integer of the signature.blockNumber the blockNumber corresponinding to the blockHash that was signed.cid the IPFS CID of the document to be associated with the device.address the address combined with the blockHash used as the digest for the signature. Set to 0000000000000000000000000000000000000000 if no address was provided during signing.Optional
name a name for the linked content.description a description for the linked content.contractAddress the contractAddress of the smart contract to be associated with the device. Only devices with a contractAddress can be revealed, e.g. KONG Passports.POST /mint : link media to a HaLo device.Post a recent signature along with a media file and metadata that you wish to associate with the device. NOTE: once successful this request is binding and the document is created permanently on Arweave.
curl --location --request POST 'http://localhost:3000/mint' \
--form 'media=@"hello.png"' \
--form 'device_id="caecb195dc849ccdb47a341c082410d55239ab3528510d4d67c016672bae2744"' \
--form 'device_sig="{ \"r\":\"ca7df33e0a3b691e0133f008a8bb77c347cb7aee3aa00fed85e96e78382c2b28\", \"s\":\"d0eec0950695d0ed94e175449b848fb72dbad1b0bb1153d96b53ffb6b8026d72\" }"' \
--form 'device_token_metadata="{ \"name\":\"HaLo NFT\" }"' \
--form 'minter_addr="0x77f0cc420dea0ae726db6bef1460a4b69176a8ea"' \
--form 'minter_sig="{ \"r\":\"61dba084cc5e7035fd5f1fb1ada4b6f9011459bea15f4d2f4eab957fc918fa5b\", \"s\":\"99ea02a0d02d5e6301b185aadd54cb56c6538518ce2096d4f49f34c9701e617d\" }"' \
--form 'blockNumber="14303538"'
If the media is successfully added to Arweavce, the server will indicate the Arweave ID and IPFS CID.
Required
media media file that is to be associated with the device. Must be less than 5Mb.device_id sha256 hash of the chip's primary public key.device_sig JSON formatted r and s components of the signature generated by the device of a recent blockhash.device_token_metadata metadata to be associated with the device in JSON format, e.g. name and description.minter_addr the Ethereum address of the minter associating the media with the HaLo chip.minter_sig JSON formatted r and s components of the EIP-712 signature generated by the minter of the device in typed schema noted below.blockNumber corresponding to the block number of the block hash signed. const typedData = {
types: {
EIP712Domain: [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "chainId", type: "uint256" },
],
Device: [
{ name: "id", type: "string" },
{ name: "signatureR", type: "string" },
{ name: "signatureS", type: "string" },
{ name: "digest", type: "string" },
],
Media: [
{ name: "cid", type: "string" },
{ name: "name", type: "string" },
{ name: "description", type: "string" },
{ name: "minter", type: "address" },
{ name: "device", type: "Device" },
],
},
primaryType: "Media",
domain: {
name: "ERS",
version: "0.1.0",
chainId: chainId,
},
message: {
cid: ipfsCid,
name: device_token_metadata.name,
description: device_token_metadata.description,
minter: address,
device: {
id: device_id,
signatureR: sigSplit.r,
signatureS: sigSplit.s,
digest: sigMsg,
},
},
};
GET /token/:address/:id : tokenUri for a SiLo-linked ERC721.Retrieve the ERC721 tokenUri details for a SiLo-linked ERC721 if available.
curl --location --request GET 'localhost:3000/token/0xd431b82796865F396e28d0f56b6a3d6626268A6e/3'
{
"name": null,
"description": null,
"image": "ipfs://QmagtqYd6D2cNHudEJQnNNNS9DTnACwjLSBJoHXea9QXaq",
"nonce": "4a90150413774ede3e1f9ba517bb723a714baf1c0f3275e6fb36d624e49af712",
"attributes": [
{
"trait_type": "statue",
"value": "Apollo"
},
{
"trait_type": "halo",
"value": "GoldHalo"
},
{
"trait_type": "material",
"value": "Aquamarine"
},
{
"trait_type": "lighting",
"value": "Gold"
},
{
"trait_type": "earrings",
"value": "None"
},
{
"trait_type": "tattoos",
"value": "None"
}
]
}
GET /token/:address : all token information for a SiLo-linked ERC721.Retrieve all ERC721 tokenUri details for a SiLo-linked ERC721 if available.
curl --location --request GET 'localhost:3000/token/0xd431b82796865F396e28d0f56b6a3d6626268A6e'
[
{
"name": null,
"description": null,
"image": "ipfs://QmagtqYd6D2cNHudEJQnNNNS9DTnACwjLSBJoHXea9QXaq",
"nonce": "4a90150413774ede3e1f9ba517bb723a714baf1c0f3275e6fb36d624e49af712",
"attributes": [
{
"trait_type": "statue",
"value": "Apollo"
},
{
"trait_type": "halo",
"value": "GoldHalo"
},
{
"trait_type": "material",
"value": "Aquamarine"
},
{
"trait_type": "lighting",
"value": "Gold"
},
{
"trait_type": "earrings",
"value": "None"
},
{
"trait_type": "tattoos",
"value": "None"
}
]
}
]
GET /reveal : start a reveal for a KONG Land NFT using a Passport.Using a recent signature from the device that you want to link along with the tokenId corresponding to the NFT, retrieve a signature from the oracle indicating that device signature verified. This oracle signature can be submitted to the RevealCitizen contract to associate the Kong Land NFT to the Passport.
curl --location --request GET 'localhost:3000/reveal?x=a1441c4e7dabb340fff0b27d26f9c0c44687a84d02a8217d7594185ccddfb06b&y=4f0d74de943e68de5ab6499e9d81058aa55c86fef20dde1ba32a073b5f805ebd&r=95278b2495c7b1507eb41e1c97ee282e0a88ed516dc96da3f93bab150a232f2e&s=e4c4ece763e7d039a9df5a1e7ef0b56cebc47e3edaace36fce09783d04ba5163&blockNumber=11516941&addr=1dCD8763c01961C2BbB5ed58C6E51F55b1378589'
If the server can successfully verify the signature against the signed blockhash, it will generate an oracleSignature in response that can be used in the RevealCitizen contract.
0xb154fae59e0295033f858e8a3b0789e81cea6465f5e3322ac653bc92d79fcb1b63d136fbb5b587d4fd641299f40dd97d4b21d4fbaa2521c71f8de883df5e57fe1b
Required
x parameter should match the X coordinate of the device's primary P256 public key.y parameter should match the Y coordinate of the device's primary P256 public key.r parameter corresponding to the R integer of the signature.s parameter corresponding to the S integer of the signature.blockNumber corresponding to the block number of the block hash signed.addr the address of the account holding the NFT that will be associated with the Passport. Strip the prepended '0x'.POST /reveal : complete a reveal for a KONG Land NFT using a Passport.Complete the reveal process by sending the transaction information from setting the Passport information in RevealCitizen. The server will review the transaction and link to the token URI if a corresponding device is found.
curl --location --request POST 'localhost:3000/reveal' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'tx=0xfb2c7172ba64dd3547a11aa6db9eb85022fbbbea03303c3082da148100589d14'
If the tx is matches a device, the server will indicate success.
TODO: redirect to the token URI.
success
Required
tx the ID of the successful transaction linking the Passport to the NFT in RevealCitizen.GET /defaults : a list of default nodes and contracts used in the KONG mobile app.curl --location --request GET 'localhost:3000/defaults'
{
"ethNode": "https://ropsten.infura.io/v3/xyz,
"ipfsNode": "https://gateway.pinata.cloud/ipfs",
"contracts": {
"registerMerkleRoot": "0x2ca8a7ecc577b3abec55ac4e74a5d3135874a5f4",
"oldRegistry": "0x41a81c92F019EbB05D3365A0E7b56D868eD2318e",
"citizenERC20": "0x4e4C7051EcCe3985403BE5C551C55b716DdbF2aB",
"citizenERC721": "0xc8b3EAD0d32E793D6549E6898b1F9e5078D9bAc2",
"revealCitizen": "0x535250a854bc2999a2798709a8c3016e60fe0600"
}
}
npm install..env file. See sample.env.npm run dev.device-sign.js is a test fixture to create signatures which can be used to validate the reveal endpoints. It requires the --address= parameter (not 0x prefixed) as well as the --blockNumber of the blockhash you wish to sign. You must also set an ETH_NODE env var.node device-sign.js --address=1dCD8763c01961C2BbB5ed58C6E51F55b1378589 --blockNumber=11345106
Note: it requires a test device JSON file (signer/test-silo.json) with a primaryPrivateKey hex string, for instance:
{ "primaryPrivateKey": "0x12345..." }
ethSigner which is derived from an encrypted Ethereum wallet (signer/wallet.json) not included in this repo. You can generate one at MyEtherWallet. The SIGNER_KEY in the .env file should match the decryption key for this generated wallet.ethers has a preference for adding '0x' while elliptic mainly handles strings without.sha256 expected by the smart contract. All the following examples will produce the same hash from pub.x and pub.y key coordinates:const xBuffer = Buffer.from(pub.x, 'hex');
const yBuffer = Buffer.from(pub.y, 'hex');
const xyBuffer = Buffer.concat([xBuffer,yBuffer]);
const pubHashFromBuffer = '0x' + crypto.createHash('sha256').update(xyBuffer).digest('hex');
const pubHashFromHex = '0x' + crypto.createHash('sha256').update(pub.x + pub.y, 'hex').digest('hex');
const pubHashEthers = ethers.utils.sha256('0x' + pub.x + pub.y);
See the RevealCitizen.sol contract in https://github.com/kong-org/citizen for an example of a reveal contract. This app expects that the contract has the following interfaces:
'function _revealCid() view returns (string)',
'function _revealERC721() view returns (address)'
revealCid: IPFS CID of the document containing the reveal attributes.revealERC721: The contract address of the NFT being revealed.See https://gateway.pinata.cloud/ipfs/QmNPY4aqViDHkMmmn8jVBWWq2e2CteVVUF43perEbYxGQA for an example of attributes.
You can create attributes that are revealed on a successful device signature.
Required
nonce: A randomly generated 32 bytes hex number associated with each set of attributes to be revealed.Optional
name: The name of the revealed NFT.description: A description of the revealed NFT.image: An image for the revealed NFT.video: A video for the revealed NFT. Note: rendering videos not currently supported.attributes: A key:value pair of attributes for the revealed NFT, e.g. 'statue':'Apollo'.