feat: verifications and mongo write operations (#253)

* integration

* refactor: rename the mintId parameter, add serverless offline.

* docs: update documentation readme.

* feat: add the create call for handling new mint info.

* feat: add build record db, write the signed transaction call to the contract, query builds in the mint handler.

* feat: new prisma schema.

* feat: add logic to the build handler and update mint handler to pass the verified field.

* feat: update token record in the build handler, add start command to package.json

* feat: add dotenv to read the private key variable from the main .env file.

* feat: add domain and ipfs hash to mint and setTokenBuild functions. Alter the structs accordingly.

* test: update mint parameters with ipfsHash for foundry and hardhat tests.

* feat: add build record entity to subgraph.

* feat: add domain field, update schema, remove tokenId from build handler.

* test: fix missing parameters.

* fix: build info test parameters missing.

* test: final test fix for the foundry metadataupdate params.

* refactor: tsconfig changes and pr feedback.
This commit is contained in:
Shredder 2023-05-09 21:25:19 +03:30 committed by GitHub
parent 393c4a316d
commit 70f2df4210
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 3268 additions and 106 deletions

View File

@ -39,6 +39,7 @@ contract FleekERC721 is
string ENS, string ENS,
string commitHash, string commitHash,
string gitRepository, string gitRepository,
string ipfsHash,
string logo, string logo,
uint24 color, uint24 color,
bool accessPointAutoApproval, bool accessPointAutoApproval,
@ -108,6 +109,7 @@ contract FleekERC721 is
string calldata ens, string calldata ens,
string memory commitHash, string memory commitHash,
string memory gitRepository, string memory gitRepository,
string memory ipfsHash,
string memory logo, string memory logo,
uint24 color, uint24 color,
bool accessPointAutoApproval, bool accessPointAutoApproval,
@ -131,7 +133,7 @@ contract FleekERC721 is
// The mint interaction is considered to be the first build of the site. Updates from now on all increment the currentBuild by one and update the mapping. // The mint interaction is considered to be the first build of the site. Updates from now on all increment the currentBuild by one and update the mapping.
app.currentBuild = 0; app.currentBuild = 0;
app.builds[0] = Build(commitHash, gitRepository); app.builds[0] = Build(commitHash, gitRepository, ipfsHash, externalURL);
emit NewMint( emit NewMint(
tokenId, tokenId,
@ -141,6 +143,7 @@ contract FleekERC721 is
ens, ens,
commitHash, commitHash,
gitRepository, gitRepository,
ipfsHash,
logo, logo,
color, color,
accessPointAutoApproval, accessPointAutoApproval,
@ -396,11 +399,14 @@ contract FleekERC721 is
function setTokenBuild( function setTokenBuild(
uint256 tokenId, uint256 tokenId,
string memory _commitHash, string memory _commitHash,
string memory _gitRepository string memory _gitRepository,
string memory _ipfsHash,
string memory _domain
) public virtual requireTokenRole(tokenId, TokenRoles.Controller) { ) public virtual requireTokenRole(tokenId, TokenRoles.Controller) {
_requireMinted(tokenId); _requireMinted(tokenId);
_apps[tokenId].builds[++_apps[tokenId].currentBuild] = Build(_commitHash, _gitRepository); _apps[tokenId].builds[++_apps[tokenId].currentBuild] = Build(_commitHash, _gitRepository, _ipfsHash, _domain);
emit MetadataUpdate(tokenId, "build", [_commitHash, _gitRepository], msg.sender); // Note from Nima: should we update the externalURL field with each new domain?
emit MetadataUpdate(tokenId, "build", [_commitHash, _gitRepository, _ipfsHash, _domain], msg.sender);
} }
/** /**

View File

@ -24,7 +24,7 @@ interface IERCX {
*/ */
event MetadataUpdate(uint256 indexed _tokenId, string key, string value, address indexed triggeredBy); event MetadataUpdate(uint256 indexed _tokenId, string key, string value, address indexed triggeredBy);
event MetadataUpdate(uint256 indexed _tokenId, string key, uint24 value, address indexed triggeredBy); event MetadataUpdate(uint256 indexed _tokenId, string key, uint24 value, address indexed triggeredBy);
event MetadataUpdate(uint256 indexed _tokenId, string key, string[2] value, address indexed triggeredBy); event MetadataUpdate(uint256 indexed _tokenId, string key, string[4] value, address indexed triggeredBy);
event MetadataUpdate(uint256 indexed _tokenId, string key, bool value, address indexed triggeredBy); event MetadataUpdate(uint256 indexed _tokenId, string key, bool value, address indexed triggeredBy);
/** /**
@ -33,6 +33,8 @@ interface IERCX {
struct Build { struct Build {
string commitHash; string commitHash;
string gitRepository; string gitRepository;
string ipfsHash;
string domain;
} }
/** /**
@ -84,7 +86,13 @@ interface IERCX {
/** /**
* @dev Sets a minted token's build. * @dev Sets a minted token's build.
*/ */
function setTokenBuild(uint256 tokenId, string memory commitHash, string memory gitRepository) external; function setTokenBuild(
uint256 tokenId,
string memory commitHash,
string memory gitRepository,
string memory ipfsHash,
string memory domain
) external;
/** /**
* @dev Returns the token metadata for a given tokenId. * @dev Returns the token metadata for a given tokenId.

View File

@ -369,29 +369,31 @@ contract Test_FleekERC721_AccessControl is Test_FleekERC721_Base, Test_FleekERC7
function test_setTokenBuild() public { function test_setTokenBuild() public {
string memory commitHash = "commitHash"; string memory commitHash = "commitHash";
string memory gitRepository = "gitRepository"; string memory gitRepository = "gitRepository";
string memory ipfsHash = "ipfsHash";
string memory domain = "domain";
// ColletionOwner // ColletionOwner
vm.prank(collectionOwner); vm.prank(collectionOwner);
expectRevertWithTokenRole(tokenId, FleekAccessControl.TokenRoles.Controller); expectRevertWithTokenRole(tokenId, FleekAccessControl.TokenRoles.Controller);
CuT.setTokenBuild(tokenId, commitHash, gitRepository); CuT.setTokenBuild(tokenId, commitHash, gitRepository, ipfsHash, domain);
// CollectionVerifier // CollectionVerifier
vm.prank(collectionVerifier); vm.prank(collectionVerifier);
expectRevertWithTokenRole(tokenId, FleekAccessControl.TokenRoles.Controller); expectRevertWithTokenRole(tokenId, FleekAccessControl.TokenRoles.Controller);
CuT.setTokenBuild(tokenId, commitHash, gitRepository); CuT.setTokenBuild(tokenId, commitHash, gitRepository, ipfsHash, domain);
// TokenOwner // TokenOwner
vm.prank(tokenOwner); vm.prank(tokenOwner);
CuT.setTokenBuild(tokenId, commitHash, gitRepository); CuT.setTokenBuild(tokenId, commitHash, gitRepository, ipfsHash, domain);
// TokenController // TokenController
vm.prank(tokenController); vm.prank(tokenController);
CuT.setTokenBuild(tokenId, commitHash, gitRepository); CuT.setTokenBuild(tokenId, commitHash, gitRepository, ipfsHash, domain);
// AnyAddress // AnyAddress
vm.prank(anyAddress); vm.prank(anyAddress);
expectRevertWithTokenRole(tokenId, FleekAccessControl.TokenRoles.Controller); expectRevertWithTokenRole(tokenId, FleekAccessControl.TokenRoles.Controller);
CuT.setTokenBuild(tokenId, commitHash, gitRepository); CuT.setTokenBuild(tokenId, commitHash, gitRepository, ipfsHash, domain);
} }
function test_burn() public { function test_burn() public {

View File

@ -54,6 +54,7 @@ contract Test_FleekERC721_Billing is Test_FleekERC721_Base, Test_FleekERC721_Bil
TestConstants.APP_ENS, TestConstants.APP_ENS,
TestConstants.APP_COMMIT_HASH, TestConstants.APP_COMMIT_HASH,
TestConstants.APP_GIT_REPOSITORY, TestConstants.APP_GIT_REPOSITORY,
TestConstants.APP_IPFS_HASH,
TestConstants.LOGO_0, TestConstants.LOGO_0,
TestConstants.APP_COLOR, TestConstants.APP_COLOR,
TestConstants.APP_ACCESS_POINT_AUTO_APPROVAL_SETTINGS, TestConstants.APP_ACCESS_POINT_AUTO_APPROVAL_SETTINGS,
@ -75,6 +76,7 @@ contract Test_FleekERC721_Billing is Test_FleekERC721_Base, Test_FleekERC721_Bil
TestConstants.APP_ENS, TestConstants.APP_ENS,
TestConstants.APP_COMMIT_HASH, TestConstants.APP_COMMIT_HASH,
TestConstants.APP_GIT_REPOSITORY, TestConstants.APP_GIT_REPOSITORY,
TestConstants.APP_IPFS_HASH,
TestConstants.LOGO_0, TestConstants.LOGO_0,
TestConstants.APP_COLOR, TestConstants.APP_COLOR,
TestConstants.APP_ACCESS_POINT_AUTO_APPROVAL_SETTINGS, TestConstants.APP_ACCESS_POINT_AUTO_APPROVAL_SETTINGS,
@ -98,6 +100,7 @@ contract Test_FleekERC721_Billing is Test_FleekERC721_Base, Test_FleekERC721_Bil
TestConstants.APP_ENS, TestConstants.APP_ENS,
TestConstants.APP_COMMIT_HASH, TestConstants.APP_COMMIT_HASH,
TestConstants.APP_GIT_REPOSITORY, TestConstants.APP_GIT_REPOSITORY,
TestConstants.APP_IPFS_HASH,
TestConstants.LOGO_0, TestConstants.LOGO_0,
TestConstants.APP_COLOR, TestConstants.APP_COLOR,
TestConstants.APP_ACCESS_POINT_AUTO_APPROVAL_SETTINGS, TestConstants.APP_ACCESS_POINT_AUTO_APPROVAL_SETTINGS,

View File

@ -15,6 +15,8 @@ library TestConstants {
string public constant APP_GIT_REPOSITORY = "https://github.com/fleekxyz/non-fungible-apps"; string public constant APP_GIT_REPOSITORY = "https://github.com/fleekxyz/non-fungible-apps";
string public constant APP_IPFS_HASH = "mtwirsqawjuoloq2gvtyug2tc3jbf5htm2zeo4rsknfiv3fdp46a";
uint24 public constant APP_COLOR = 0x123456; uint24 public constant APP_COLOR = 0x123456;
bool public constant APP_ACCESS_POINT_AUTO_APPROVAL_SETTINGS = true; bool public constant APP_ACCESS_POINT_AUTO_APPROVAL_SETTINGS = true;

View File

@ -39,6 +39,8 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base {
string memory newENS, string memory newENS,
string memory newCommitHash, string memory newCommitHash,
string memory newRepository, string memory newRepository,
string memory newIpfsHash,
string memory newDomain,
string memory newLogo, string memory newLogo,
uint24 newColor uint24 newColor
) public { ) public {
@ -47,7 +49,7 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base {
CuT.setTokenExternalURL(tokenId, newExternalURL); CuT.setTokenExternalURL(tokenId, newExternalURL);
transferENS(newENS, deployer); transferENS(newENS, deployer);
CuT.setTokenENS(tokenId, newENS); CuT.setTokenENS(tokenId, newENS);
CuT.setTokenBuild(tokenId, newCommitHash, newRepository); CuT.setTokenBuild(tokenId, newCommitHash, newRepository, newIpfsHash, newDomain);
CuT.setTokenLogoAndColor(tokenId, newLogo, newColor); CuT.setTokenLogoAndColor(tokenId, newLogo, newColor);
( (

View File

@ -36,6 +36,7 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base {
"fleek.eth", "fleek.eth",
"94e8ba38568aea4fb277a37a4c472d94a6ce880a", "94e8ba38568aea4fb277a37a4c472d94a6ce880a",
"https://github.com/a-different/repository", "https://github.com/a-different/repository",
"mtwirsqawjuoloq2gvtyug2tc3jbf5htm2zeo4rsknfiv3fdp46a",
TestConstants.LOGO_1, TestConstants.LOGO_1,
0x654321, 0x654321,
false, false,
@ -56,6 +57,7 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base {
"fleek.eth", "fleek.eth",
"94e8ba38568aea4fb277a37a4c472d94a6ce880a", "94e8ba38568aea4fb277a37a4c472d94a6ce880a",
"https://github.com/a-different/repository", "https://github.com/a-different/repository",
"mtwirsqawjuoloq2gvtyug2tc3jbf5htm2zeo4rsknfiv3fdp46a",
TestConstants.LOGO_1, TestConstants.LOGO_1,
0x654321, 0x654321,
true, true,
@ -81,6 +83,7 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base {
string memory ens, string memory ens,
string memory commitHash, string memory commitHash,
string memory gitRepository, string memory gitRepository,
string memory ipfsHash,
string memory logo, string memory logo,
uint24 color, uint24 color,
bool autoApprovalAp bool autoApprovalAp
@ -95,6 +98,7 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base {
ens, ens,
commitHash, commitHash,
gitRepository, gitRepository,
ipfsHash,
logo, logo,
color, color,
autoApprovalAp, autoApprovalAp,
@ -115,6 +119,7 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base {
TestConstants.APP_ENS, TestConstants.APP_ENS,
TestConstants.APP_COMMIT_HASH, TestConstants.APP_COMMIT_HASH,
TestConstants.APP_GIT_REPOSITORY, TestConstants.APP_GIT_REPOSITORY,
TestConstants.APP_IPFS_HASH,
TestConstants.LOGO_0, TestConstants.LOGO_0,
TestConstants.APP_COLOR, TestConstants.APP_COLOR,
false, false,
@ -131,6 +136,7 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base {
"", "",
TestConstants.APP_COMMIT_HASH, TestConstants.APP_COMMIT_HASH,
TestConstants.APP_GIT_REPOSITORY, TestConstants.APP_GIT_REPOSITORY,
TestConstants.APP_IPFS_HASH,
TestConstants.LOGO_0, TestConstants.LOGO_0,
TestConstants.APP_COLOR, TestConstants.APP_COLOR,
false, false,

View File

@ -81,6 +81,7 @@ abstract contract Test_FleekERC721_Base is Test, Test_FleekERC721_Assertions {
TestConstants.APP_ENS, TestConstants.APP_ENS,
TestConstants.APP_COMMIT_HASH, TestConstants.APP_COMMIT_HASH,
TestConstants.APP_GIT_REPOSITORY, TestConstants.APP_GIT_REPOSITORY,
TestConstants.APP_IPFS_HASH,
TestConstants.LOGO_0, TestConstants.LOGO_0,
TestConstants.APP_COLOR, TestConstants.APP_COLOR,
false, // Auto Approval Is OFF false, // Auto Approval Is OFF

View File

@ -6,7 +6,7 @@ import "./TestBase.sol";
contract Test_FleekERC721_TokenURIAssertions is Test { contract Test_FleekERC721_TokenURIAssertions is Test {
event MetadataUpdate(uint256 indexed _tokenId, string key, string value, address indexed triggeredBy); event MetadataUpdate(uint256 indexed _tokenId, string key, string value, address indexed triggeredBy);
event MetadataUpdate(uint256 indexed _tokenId, string key, string[2] value, address indexed triggeredBy); event MetadataUpdate(uint256 indexed _tokenId, string key, string[4] value, address indexed triggeredBy);
event MetadataUpdate(uint256 indexed _tokenId, string key, uint24 value, address indexed triggeredBy); event MetadataUpdate(uint256 indexed _tokenId, string key, uint24 value, address indexed triggeredBy);
function expectMetadataUpdate( function expectMetadataUpdate(
@ -22,7 +22,7 @@ contract Test_FleekERC721_TokenURIAssertions is Test {
function expectMetadataUpdate( function expectMetadataUpdate(
uint256 _tokenId, uint256 _tokenId,
string memory key, string memory key,
string[2] memory value, string[4] memory value,
address triggeredBy address triggeredBy
) public { ) public {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
@ -57,7 +57,13 @@ contract Test_FleekERC721_TokenURI is Test_FleekERC721_Base, Test_FleekERC721_To
CuT.setTokenExternalURL(tokenId, "https://new-url.com"); CuT.setTokenExternalURL(tokenId, "https://new-url.com");
transferENS("new-ens.eth", deployer); transferENS("new-ens.eth", deployer);
CuT.setTokenENS(tokenId, "new-ens.eth"); CuT.setTokenENS(tokenId, "new-ens.eth");
CuT.setTokenBuild(tokenId, "ce1a3fc141e29f8e1d00a654e156c4982d7711bf", "https://github.com/other/repo"); CuT.setTokenBuild(
tokenId,
"ce1a3fc141e29f8e1d00a654e156c4982d7711bf",
"https://github.com/other/repo",
"ipfsHash",
"domain"
);
CuT.setTokenLogoAndColor(tokenId, TestConstants.LOGO_1, 0x654321); CuT.setTokenLogoAndColor(tokenId, TestConstants.LOGO_1, 0x654321);
CuT.setTokenVerified(tokenId, true); CuT.setTokenVerified(tokenId, true);
@ -96,10 +102,16 @@ contract Test_FleekERC721_TokenURI is Test_FleekERC721_Base, Test_FleekERC721_To
expectMetadataUpdate( expectMetadataUpdate(
tokenId, tokenId,
"build", "build",
["ce1a3fc141e29f8e1d00a654e156c4982d7711bf", "https://github.com/other/repo"], ["ce1a3fc141e29f8e1d00a654e156c4982d7711bf", "https://github.com/other/repo", "ipfshash", "domain"],
deployer deployer
); );
CuT.setTokenBuild(tokenId, "ce1a3fc141e29f8e1d00a654e156c4982d7711bf", "https://github.com/other/repo"); CuT.setTokenBuild(
tokenId,
"ce1a3fc141e29f8e1d00a654e156c4982d7711bf",
"https://github.com/other/repo",
"ipfshash",
"domain"
);
expectMetadataUpdate(tokenId, "logo", TestConstants.LOGO_1, deployer); expectMetadataUpdate(tokenId, "logo", TestConstants.LOGO_1, deployer);
CuT.setTokenLogo(tokenId, TestConstants.LOGO_1); CuT.setTokenLogo(tokenId, TestConstants.LOGO_1);

View File

@ -21,6 +21,7 @@ describe('FleekERC721.Billing', () => {
MintParams.ens, MintParams.ens,
MintParams.commitHash, MintParams.commitHash,
MintParams.gitRepository, MintParams.gitRepository,
MintParams.ipfsHash,
MintParams.logo, MintParams.logo,
MintParams.color, MintParams.color,
MintParams.accessPointAutoApprovalSettings, MintParams.accessPointAutoApprovalSettings,

View File

@ -187,6 +187,7 @@ describe('FleekERC721.CollectionRoles', () => {
TestConstants.MintParams.ens, TestConstants.MintParams.ens,
TestConstants.MintParams.commitHash, TestConstants.MintParams.commitHash,
TestConstants.MintParams.gitRepository, TestConstants.MintParams.gitRepository,
TestConstants.MintParams.ipfsHash,
TestConstants.MintParams.logo, TestConstants.MintParams.logo,
TestConstants.MintParams.color, TestConstants.MintParams.color,
TestConstants.MintParams.accessPointAutoApprovalSettings, TestConstants.MintParams.accessPointAutoApprovalSettings,

View File

@ -22,6 +22,7 @@ describe('FleekERC721.ENS', () => {
'app.eth', 'app.eth',
MintParams.commitHash, MintParams.commitHash,
MintParams.gitRepository, MintParams.gitRepository,
MintParams.ipfsHash,
MintParams.logo, MintParams.logo,
MintParams.color, MintParams.color,
MintParams.accessPointAutoApprovalSettings, MintParams.accessPointAutoApprovalSettings,
@ -43,6 +44,7 @@ describe('FleekERC721.ENS', () => {
'app.eth', 'app.eth',
MintParams.commitHash, MintParams.commitHash,
MintParams.gitRepository, MintParams.gitRepository,
MintParams.ipfsHash,
MintParams.logo, MintParams.logo,
MintParams.color, MintParams.color,
MintParams.accessPointAutoApprovalSettings, MintParams.accessPointAutoApprovalSettings,

View File

@ -14,6 +14,7 @@ describe('FleekERC721.GetLastTokenId', () => {
TestConstants.MintParams.ens, TestConstants.MintParams.ens,
TestConstants.MintParams.commitHash, TestConstants.MintParams.commitHash,
TestConstants.MintParams.gitRepository, TestConstants.MintParams.gitRepository,
TestConstants.MintParams.ipfsHash,
TestConstants.MintParams.logo, TestConstants.MintParams.logo,
TestConstants.MintParams.color, TestConstants.MintParams.color,
false, false,

View File

@ -23,6 +23,7 @@ export const TestConstants = Object.freeze({
externalUrl: 'https://fleek.co', externalUrl: 'https://fleek.co',
commitHash: 'b72e47171746b6a9e29b801af9cb655ecf4d665c', commitHash: 'b72e47171746b6a9e29b801af9cb655ecf4d665c',
gitRepository: 'https://github.com/fleekxyz/non-fungible-apps', gitRepository: 'https://github.com/fleekxyz/non-fungible-apps',
ipfsHash: 'mtwirsqawjuoloq2gvtyug2tc3jbf5htm2zeo4rsknfiv3fdp46a',
logo: 'data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI1MDAiIHdpZHRoPSIyMTgzIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjQgMTQxLjUzMTk5OTk5OTk5OTk4Ij48cGF0aCBkPSJNMTAuMzgzIDEyNi44OTRMMCAwbDEyNCAuMjU1LTEwLjk3OSAxMjYuNjM5LTUwLjU1MyAxNC42Mzh6IiBmaWxsPSIjZTM0ZjI2Ii8+PHBhdGggZD0iTTYyLjQ2OCAxMjkuMjc3VjEyLjA4NWw1MS4wNjQuMTctOS4xMDYgMTA0Ljg1MXoiIGZpbGw9IiNlZjY1MmEiLz48cGF0aCBkPSJNOTkuNDkgNDEuMzYybDEuNDQ2LTE1LjQ5SDIyLjM4M2w0LjM0IDQ3LjQ5aDU0LjIxM0w3OC44MSA5My42MTdsLTE3LjM2MiA0LjY4LTE3LjYxNy01LjEwNi0uOTM2LTEyLjA4NUgyNy4zMTlsMi4xMjggMjQuNjgxIDMyIDguOTM2IDMyLjI1NS04LjkzNiA0LjM0LTQ4LjE3SDQxLjEwN0wzOS40OSA0MS4zNjJ6IiBmaWxsPSIjZmZmIi8+PC9zdmc+', logo: 'data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI1MDAiIHdpZHRoPSIyMTgzIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjQgMTQxLjUzMTk5OTk5OTk5OTk4Ij48cGF0aCBkPSJNMTAuMzgzIDEyNi44OTRMMCAwbDEyNCAuMjU1LTEwLjk3OSAxMjYuNjM5LTUwLjU1MyAxNC42Mzh6IiBmaWxsPSIjZTM0ZjI2Ii8+PHBhdGggZD0iTTYyLjQ2OCAxMjkuMjc3VjEyLjA4NWw1MS4wNjQuMTctOS4xMDYgMTA0Ljg1MXoiIGZpbGw9IiNlZjY1MmEiLz48cGF0aCBkPSJNOTkuNDkgNDEuMzYybDEuNDQ2LTE1LjQ5SDIyLjM4M2w0LjM0IDQ3LjQ5aDU0LjIxM0w3OC44MSA5My42MTdsLTE3LjM2MiA0LjY4LTE3LjYxNy01LjEwNi0uOTM2LTEyLjA4NUgyNy4zMTlsMi4xMjggMjQuNjgxIDMyIDguOTM2IDMyLjI1NS04LjkzNiA0LjM0LTQ4LjE3SDQxLjEwN0wzOS40OSA0MS4zNjJ6IiBmaWxsPSIjZmZmIi8+PC9zdmc+',
color: 0xe34f26, color: 0xe34f26,
accessPointAutoApprovalSettings: false, accessPointAutoApprovalSettings: false,

View File

@ -2,6 +2,6 @@ export const Events = Object.freeze({
MetadataUpdate: { MetadataUpdate: {
string: 'MetadataUpdate(uint256,string,string,address)', string: 'MetadataUpdate(uint256,string,string,address)',
uint24: 'MetadataUpdate(uint256,string,uint24,address)', uint24: 'MetadataUpdate(uint256,string,uint24,address)',
stringTuple: 'MetadataUpdate(uint256,string,string[2],address)', stringArray4: 'MetadataUpdate(uint256,string,string[4],address)',
}, },
}); });

View File

@ -44,6 +44,7 @@ export abstract class Fixtures {
TestConstants.MintParams.ens, TestConstants.MintParams.ens,
TestConstants.MintParams.commitHash, TestConstants.MintParams.commitHash,
TestConstants.MintParams.gitRepository, TestConstants.MintParams.gitRepository,
TestConstants.MintParams.ipfsHash,
TestConstants.MintParams.logo, TestConstants.MintParams.logo,
TestConstants.MintParams.color, TestConstants.MintParams.color,
TestConstants.MintParams.accessPointAutoApprovalSettings, TestConstants.MintParams.accessPointAutoApprovalSettings,

View File

@ -17,6 +17,7 @@ describe('FleekERC721.Minting', () => {
MintParams.ens, MintParams.ens,
MintParams.commitHash, MintParams.commitHash,
MintParams.gitRepository, MintParams.gitRepository,
MintParams.ipfsHash,
MintParams.logo, MintParams.logo,
MintParams.color, MintParams.color,
MintParams.accessPointAutoApprovalSettings, MintParams.accessPointAutoApprovalSettings,
@ -40,6 +41,7 @@ describe('FleekERC721.Minting', () => {
MintParams.ens, MintParams.ens,
MintParams.commitHash, MintParams.commitHash,
MintParams.gitRepository, MintParams.gitRepository,
MintParams.ipfsHash,
MintParams.logo, MintParams.logo,
MintParams.color, MintParams.color,
MintParams.accessPointAutoApprovalSettings, MintParams.accessPointAutoApprovalSettings,
@ -66,6 +68,7 @@ describe('FleekERC721.Minting', () => {
MintParams.ens, MintParams.ens,
MintParams.commitHash, MintParams.commitHash,
MintParams.gitRepository, MintParams.gitRepository,
MintParams.ipfsHash,
MintParams.logo, MintParams.logo,
MintParams.color, MintParams.color,
MintParams.accessPointAutoApprovalSettings, MintParams.accessPointAutoApprovalSettings,
@ -87,6 +90,7 @@ describe('FleekERC721.Minting', () => {
'', '',
MintParams.commitHash, MintParams.commitHash,
MintParams.gitRepository, MintParams.gitRepository,
MintParams.ipfsHash,
MintParams.logo, MintParams.logo,
MintParams.color, MintParams.color,
MintParams.accessPointAutoApprovalSettings, MintParams.accessPointAutoApprovalSettings,

View File

@ -18,6 +18,7 @@ describe('FleekERC721.Pausable', () => {
MintParams.ens, MintParams.ens,
MintParams.commitHash, MintParams.commitHash,
MintParams.gitRepository, MintParams.gitRepository,
MintParams.ipfsHash,
MintParams.logo, MintParams.logo,
MintParams.color, MintParams.color,
false, false,

View File

@ -51,12 +51,20 @@ describe('FleekERC721.UpdateProperties', () => {
it('should emit event for build change', async () => { it('should emit event for build change', async () => {
const { contract, tokenId, owner } = fixture; const { contract, tokenId, owner } = fixture;
await expect(contract.setTokenBuild(tokenId, 'commitHash', 'gitRepository')) await expect(
.to.emit(contract, Events.MetadataUpdate.stringTuple) contract.setTokenBuild(
tokenId,
'commitHash',
'gitRepository',
'ipfsHash',
'domain'
)
)
.to.emit(contract, Events.MetadataUpdate.stringArray4)
.withArgs( .withArgs(
tokenId, tokenId,
'build', 'build',
['commitHash', 'gitRepository'], ['commitHash', 'gitRepository', 'ipfsHash', 'domain'],
owner.address owner.address
); );
}); });

View File

@ -99,6 +99,7 @@ describe('Deploy', () => {
TestConstants.MintParams.ens, TestConstants.MintParams.ens,
TestConstants.MintParams.commitHash, TestConstants.MintParams.commitHash,
TestConstants.MintParams.gitRepository, TestConstants.MintParams.gitRepository,
TestConstants.MintParams.ipfsHash,
TestConstants.MintParams.logo, TestConstants.MintParams.logo,
TestConstants.MintParams.color, TestConstants.MintParams.color,
TestConstants.MintParams.accessPointAutoApprovalSettings, TestConstants.MintParams.accessPointAutoApprovalSettings,

View File

@ -33,6 +33,7 @@
"pinst": "^3.0.0", "pinst": "^3.0.0",
"prettier": "^2.8.4", "prettier": "^2.8.4",
"prettier-plugin-solidity": "^1.0.0", "prettier-plugin-solidity": "^1.0.0",
"serverless-offline": "^12.0.4",
"typescript": "^4.9.5" "typescript": "^4.9.5"
} }
} }

View File

@ -37,6 +37,22 @@ To deploy to development environment:
To deploy to production environment: To deploy to production environment:
`yarn sls deploy --stage prd` `yarn sls deploy --stage prd`
### Running MongoDB
The first step to run MongoDB is making sure the service is installed on the machine locally. You can check the [official MongoDB website](https://www.mongodb.com/docs/manual/installation/#mongodb-installation-tutorials) for more information on the installation process.
To process database transactions such as `create` calls, Prisma needs the MongoDB instance to be running as a replica set. Run the commands below to start a replica set with `mongod` and `mongosh`:
```
// You should replace the dbpath with the actual path on your machine and assign a name to your replica set. (Default path on linux is: /var/lib/mongodb)
// Do not close the terminal tab after running mongod.
$ sudo mongod --port 27017 --dbpath /path/to/db --replSet replicaName --bind_ip localhost,127.0.0.1
// Start a mongosh session and run the replica set initiation command in the mongo shell.
$ mongosh
> rs.initiate()
```
Make sure you copy the connection string that is presented in the `Connecting to` field when the mongosh service starts to run. We need the connection string to access the replica set. Rename the `.env.example` file to `.env` and replace the connection string placeholder in the file with the one you copied.
### Prisma configuration ### Prisma configuration

View File

@ -7,7 +7,8 @@
"build": "yarn tsc", "build": "yarn tsc",
"invoke:build": "yarn build && serverless invoke local --function submitBuildInfo", "invoke:build": "yarn build && serverless invoke local --function submitBuildInfo",
"prisma:generate": "npx prisma generate", "prisma:generate": "npx prisma generate",
"prisma:pull": "npx prisma db pull" "prisma:pull": "npx prisma db pull --force",
"start": "serverless offline"
}, },
"author": "fleek", "author": "fleek",
"license": "MIT", "license": "MIT",
@ -30,12 +31,13 @@
"@middy/http-json-body-parser": "^4.2.7", "@middy/http-json-body-parser": "^4.2.7",
"@middy/http-response-serializer": "^4.2.8", "@middy/http-response-serializer": "^4.2.8",
"@prisma/client": "^4.13.0", "@prisma/client": "^4.13.0",
"aws-sdk": "^2.1342.0",
"prisma": "^4.13.0",
"uuid": "^9.0.0",
"@types/node": "^18.15.11", "@types/node": "^18.15.11",
"aws-sdk": "^2.1342.0",
"dotenv": "^16.0.3",
"prisma": "^4.13.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"typescript": "^5.0.4", "typescript": "^5.0.4",
"uuid": "^9.0.0",
"web3": "^1.9.0" "web3": "^1.9.0"
} }
} }

View File

@ -7,10 +7,21 @@ datasource db {
url = env("DATABASE_URL") url = env("DATABASE_URL")
} }
model tokens { model builds {
id String @id @default(auto()) @map("_id") @db.ObjectId id String @id @default(auto()) @map("_id") @db.ObjectId
commit_hash String commitHash String
github_url String domain String
owner String githubRepository String
tokenId Int ipfsHash String
}
model tokens {
id String @id @default(auto()) @map("_id") @db.ObjectId
commitHash String
domain String
githubRepository String
ipfsHash String
owner String
tokenId Int
verified Boolean
} }

View File

@ -1,30 +1,91 @@
import { APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda'; import { APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda';
import { formatJSONResponse } from '@libs/api-gateway'; import { formatJSONResponse } from '@libs/api-gateway';
const querystring = require('querystring');
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { nfaContract } from '@libs/nfa-contract'; import { prisma } from '@libs/prisma';
import { account, nfaContract } from '@libs/nfa-contract';
export const submitBuildInfo = async ( export const submitBuildInfo = async (
event: APIGatewayEvent event: APIGatewayEvent
): Promise<APIGatewayProxyResult> => { ): Promise<APIGatewayProxyResult> => {
try { try {
const eventData = querystring.parse(event.body); if (event.body === null) {
return formatJSONResponse({
status: 422,
message: 'Required parameters were not passed.',
});
}
const data = JSON.parse(event.body);
const id = v4(); const id = v4();
const buildInfo = { const buildInfo = {
buildId: id, buildId: id,
createdAt: new Date().toISOString(), createdAt: new Date().toISOString(),
submittedData: eventData, githubRepository: data.githubRepository,
commitHash: data.commitHash,
ipfsHash: data.ipfsHash,
domain: data.domain,
}; };
// place holder call // Add build record to the database, if it's not already added
nfaContract.methods const buildRecord = await prisma.builds.findMany({
.setTokenBuild(1, 'hash', 'repo') where: {
.call((err: string | undefined, res: any) => { commitHash: buildInfo.commitHash,
if (err) throw new Error(err); githubRepository: buildInfo.githubRepository,
console.log('result'); ipfsHash: buildInfo.ipfsHash,
console.log(res); domain: buildInfo.domain,
},
});
if (buildRecord.length == 0) {
await prisma.builds.create({
data: {
githubRepository: buildInfo.githubRepository,
commitHash: buildInfo.commitHash,
ipfsHash: buildInfo.ipfsHash,
domain: buildInfo.domain,
},
}); });
}
const mintRecord = await prisma.tokens.findMany({
where: {
ipfsHash: buildInfo.ipfsHash,
domain: buildInfo.domain,
commitHash: buildInfo.commitHash,
githubRepository: buildInfo.githubRepository,
verified: false,
},
});
if (mintRecord.length > 0) {
// Trigger verification
// Mark the token as verified in the contract
// call the `setTokenVerified` method
await nfaContract.methods
.setTokenVerified(mintRecord[0].tokenId, true)
.send({
from: account.address,
gas: '1000000',
})
.catch(console.error);
// Update the database record in the tokens collection
await prisma.tokens.updateMany({
where: {
ipfsHash: buildInfo.ipfsHash,
domain: buildInfo.domain,
commitHash: buildInfo.commitHash,
githubRepository: buildInfo.githubRepository,
verified: false,
},
data: {
verified: true,
},
});
}
return formatJSONResponse({ return formatJSONResponse({
buildInfo, buildInfo,

View File

@ -6,31 +6,185 @@ import {
import { formatJSONResponse } from '@libs/api-gateway'; import { formatJSONResponse } from '@libs/api-gateway';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { initPrisma, prisma } from '@libs/prisma';
import { account, nfaContract, web3 } from '@libs/nfa-contract';
export const submitMintInfo = async ( export const submitMintInfo = async (
event: APIGatewayEvent event: APIGatewayEvent
///context: APIGatewayEventRequestContext ///context: APIGatewayEventRequestContext
): Promise<APIGatewayProxyResult> => { ): Promise<APIGatewayProxyResult> => {
try { try {
if (event.body === null) {
return formatJSONResponse({
status: 422,
message: 'Required parameters were not passed.',
});
}
const id = v4(); const id = v4();
/**if (!verifyAlchemySig(event.headers.xalchemywork)) { /**if (!verifyAlchemySig(event.headers.xalchemywork)) {
throw new Error('Invalid sig'); throw new Error('Invalid sig');
}**/ }**/
if (event.body == undefined) { const eventBody = JSON.parse(event.body);
throw new Error('Undefined data'); const topics = eventBody.event.data.block.logs[1].slice(1, 3);
} const hexCalldata = eventBody.event.data.block.logs[1].data;
const decodedLogs = web3.eth.abi.decodeLog(
[
{
indexed: true,
internalType: 'uint256',
name: 'tokenId',
type: 'uint256',
},
{
indexed: false,
internalType: 'string',
name: 'name',
type: 'string',
},
{
indexed: false,
internalType: 'string',
name: 'description',
type: 'string',
},
{
indexed: false,
internalType: 'string',
name: 'externalURL',
type: 'string',
},
{
indexed: false,
internalType: 'string',
name: 'ENS',
type: 'string',
},
{
indexed: false,
internalType: 'string',
name: 'commitHash',
type: 'string',
},
{
indexed: false,
internalType: 'string',
name: 'gitRepository',
type: 'string',
},
{
indexed: false,
internalType: 'string',
name: 'ipfsHash',
type: 'string',
},
{
indexed: false,
internalType: 'string',
name: 'logo',
type: 'string',
},
{
indexed: false,
internalType: 'uint24',
name: 'color',
type: 'uint24',
},
{
indexed: false,
internalType: 'bool',
name: 'accessPointAutoApproval',
type: 'bool',
},
{
indexed: true,
internalType: 'address',
name: 'minter',
type: 'address',
},
{
indexed: true,
internalType: 'address',
name: 'owner',
type: 'address',
},
{
indexed: false,
internalType: 'address',
name: 'verifier',
type: 'address',
},
],
hexCalldata,
topics
);
const mintInfo = { const mintInfo = {
buildId: id, mintId: id,
createdAt: new Date().toISOString(), createdAt: new Date().toISOString(),
body: JSON.parse(event.body), tokenId: decodedLogs.tokenId,
githubRepository: decodedLogs.gitRepository,
commit_hash: decodedLogs.commitHash,
owner: decodedLogs.owner,
ipfsHash: decodedLogs.ipfsHash,
domain: decodedLogs.externalURL,
}; };
// check if we have it in mongo initPrisma();
// if so, trigger verification call
// if not, add to mongo // Check if there is any build associated with the repository, commit hash, tokenId, and ipfsHash
const build = await prisma.builds.findMany({
where: {
githubRepository: mintInfo.githubRepository,
commitHash: mintInfo.commit_hash,
ipfsHash: mintInfo.ipfsHash,
domain: mintInfo.domain,
},
});
let verified = false;
if (build.length > 0) {
// Mark the token as verified in the contract
try {
// call the `setTokenVerified` method
await nfaContract.methods
.setTokenVerified(mintInfo.tokenId, true)
.send({
from: account.address,
gas: '1000000',
});
verified = true;
} catch (error) {
// catch transaction error
console.error(error);
}
}
// Add the record to the database
const token = await prisma.tokens.findMany({
where: {
tokenId: Number(mintInfo.tokenId),
},
});
if (token.length == 0) {
await prisma.tokens.create({
data: {
tokenId: Number(mintInfo.tokenId),
githubRepository: mintInfo.githubRepository,
commitHash: mintInfo.commit_hash,
owner: mintInfo.owner,
ipfsHash: mintInfo.ipfsHash,
verified: verified,
domain: mintInfo.domain,
},
});
}
return formatJSONResponse({ return formatJSONResponse({
mintInfo, mintInfo,

View File

@ -1,9 +1,18 @@
import Web3 from 'web3'; import Web3 from 'web3';
import * as abiFile from '../../../contracts/deployments/goerli/FleekERC721.json'; import * as abiFile from '../../../contracts/deployments/goerli/FleekERC721.json';
import * as dotenv from 'dotenv';
dotenv.config();
if (process.env.PRIVATE_KEY === undefined) {
throw Error('Private key environment variable not set.');
}
const contract_address = abiFile.address; const contract_address = abiFile.address;
const abi = abiFile.abi as any; export const abi = abiFile.abi as any;
const web3 = new Web3('https://rpc.goerli.mudit.blog');
export const web3 = new Web3('https://rpc.goerli.mudit.blog');
export const nfaContract = new web3.eth.Contract(abi, contract_address); export const nfaContract = new web3.eth.Contract(abi, contract_address);
export const account = web3.eth.accounts.privateKeyToAccount(
process.env.PRIVATE_KEY
);

View File

@ -10,7 +10,9 @@ export async function initPrisma() {
initPrisma() initPrisma()
.catch(async (e) => { .catch(async (e) => {
console.error(e); console.error(e);
})
.finally(async () => {
await prisma.$disconnect(); await prisma.$disconnect();
process.exit(1);
})
.finally(() => {
prisma.$disconnect();
}); });

View File

@ -11,7 +11,6 @@
"outDir": "dist", "outDir": "dist",
"target": "es2016", "target": "es2016",
"module": "commonjs", "module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"strict": true, "strict": true,
"skipLibCheck": true, "skipLibCheck": true,

View File

@ -1588,7 +1588,7 @@
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz" resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz"
integrity sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ== integrity sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==
"@types/node@*", "@types/node@^18.15.5": "@types/node@*":
version "18.15.5" version "18.15.5"
resolved "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz" resolved "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz"
integrity sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew== integrity sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==
@ -1598,6 +1598,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240"
integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==
"@types/node@^18.15.11":
version "18.16.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.1.tgz#5db121e9c5352925bb1f1b892c4ae620e3526799"
integrity sha512-DZxSZWXxFfOlx7k7Rv4LAyiMroaxa3Ly/7OOzZO8cBNho0YzAi4qlbrx8W27JGqG57IgR/6J7r+nOJWw6kcvZA==
"@types/pbkdf2@^3.0.0": "@types/pbkdf2@^3.0.0":
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1"
@ -2767,7 +2772,7 @@ dotenv-expand@^9.0.0:
dotenv@^16.0.3: dotenv@^16.0.3:
version "16.0.3" version "16.0.3"
resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07"
integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==
duration@^0.2.2: duration@^0.2.2:
@ -6262,10 +6267,10 @@ typedarray-to-buffer@^3.1.5:
dependencies: dependencies:
is-typedarray "^1.0.0" is-typedarray "^1.0.0"
typescript@^5.0.2: typescript@^5.0.4:
version "5.0.2" version "5.0.4"
resolved "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b"
integrity sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw== integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==
ultron@~1.1.0: ultron@~1.1.0:
version "1.1.1" version "1.1.1"

View File

@ -27,6 +27,7 @@ type NewMint @entity(immutable: true) {
ENS: String! ENS: String!
commitHash: String! # string commitHash: String! # string
gitRepository: String! # string gitRepository: String! # string
ipfsHash: String!
logo: String! logo: String!
color: Int! color: Int!
accessPointAutoApproval: Boolean! accessPointAutoApproval: Boolean!
@ -44,7 +45,7 @@ type MetadataUpdate @entity(immutable: true) {
key: String! key: String!
stringValue: String stringValue: String
uint24Value: Int uint24Value: Int
doubleStringValue: [String!]! multipleStringValue: [String!]!
booleanValue: Boolean booleanValue: Boolean
byAddress: Bytes! byAddress: Bytes!
blockNumber: BigInt! blockNumber: BigInt!
@ -76,12 +77,20 @@ type Token @entity {
owner: Owner! owner: Owner!
mintedBy: Bytes! mintedBy: Bytes!
controllers: [Controller!] controllers: [Controller!]
gitRepository: GitRepository!
commitHash: String!
accessPoints: [AccessPoint!] @derivedFrom(field: "token") accessPoints: [AccessPoint!] @derivedFrom(field: "token")
verifier: Verifier # Address verifier: Verifier # Address
verified: Boolean! verified: Boolean!
createdAt: BigInt! createdAt: BigInt!
builds: [Build!]!
}
type Build @entity {
id: Bytes! # Token ID
gitRepository: GitRepository!
commitHash: String!
ipfsHash: String!
domain: String!
token: Token! @derivedFrom(field: "builds")
} }
# Owner entity for collection, access points, and tokens # Owner entity for collection, access points, and tokens
@ -106,7 +115,7 @@ type Verifier @entity {
type GitRepository @entity { type GitRepository @entity {
id: String! # transaction hash of the first transaction this repository appeared in id: String! # transaction hash of the first transaction this repository appeared in
tokens: [Token!] @derivedFrom(field: "gitRepository") builds: [Build!] @derivedFrom(field: "gitRepository")
} }
type AccessPoint @entity { type AccessPoint @entity {

View File

@ -13,6 +13,7 @@ import {
GitRepository as GitRepositoryEntity, GitRepository as GitRepositoryEntity,
MetadataUpdate, MetadataUpdate,
Token, Token,
Build,
} from '../generated/schema'; } from '../generated/schema';
export function handleMetadataUpdateWithStringValue( export function handleMetadataUpdateWithStringValue(
@ -61,7 +62,7 @@ export function handleMetadataUpdateWithStringValue(
} }
} }
export function handleMetadataUpdateWithDoubleStringValue( export function handleMetadataUpdateWithMultipleStringValues(
event: MetadataUpdateEvent3 event: MetadataUpdateEvent3
): void { ): void {
/** /**
@ -73,30 +74,29 @@ export function handleMetadataUpdateWithDoubleStringValue(
entity.key = event.params.key; entity.key = event.params.key;
entity.tokenId = event.params._tokenId; entity.tokenId = event.params._tokenId;
entity.doubleStringValue = event.params.value; entity.multipleStringValue = event.params.value;
entity.blockNumber = event.block.number; entity.blockNumber = event.block.number;
entity.blockTimestamp = event.block.timestamp; entity.blockTimestamp = event.block.timestamp;
entity.transactionHash = event.transaction.hash; entity.transactionHash = event.transaction.hash;
entity.save(); entity.save();
// UPDATE TOKEN // CREATE BUILD
const token = Token.load( const build = new Build(
Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId)) Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId))
); );
if (event.params.key == 'build') {
if (token) { let gitRepositoryEntity = GitRepositoryEntity.load(event.params.value[1]);
if (event.params.key == 'build') { if (!gitRepositoryEntity) {
let gitRepositoryEntity = GitRepositoryEntity.load(event.params.value[1]); // Create a new gitRepository entity
if (!gitRepositoryEntity) { gitRepositoryEntity = new GitRepositoryEntity(event.params.value[1]);
// Create a new gitRepository entity
gitRepositoryEntity = new GitRepositoryEntity(event.params.value[1]);
}
token.commitHash = event.params.value[0];
token.gitRepository = event.params.value[1];
token.save();
gitRepositoryEntity.save();
} }
build.commitHash = event.params.value[0];
build.gitRepository = event.params.value[1];
build.ipfsHash = event.params.value[2];
build.domain = event.params.value[3];
build.save();
gitRepositoryEntity.save();
} }
} }

View File

@ -23,6 +23,7 @@ export function handleNewMint(event: NewMintEvent): void {
const externalURL = event.params.externalURL; const externalURL = event.params.externalURL;
const ENS = event.params.ENS; const ENS = event.params.ENS;
const gitRepository = event.params.gitRepository; const gitRepository = event.params.gitRepository;
const ipfsHash = event.params.ipfsHash;
const commitHash = event.params.commitHash; const commitHash = event.params.commitHash;
const logo = event.params.logo; const logo = event.params.logo;
const color = event.params.color; const color = event.params.color;
@ -38,6 +39,7 @@ export function handleNewMint(event: NewMintEvent): void {
newMintEntity.ENS = ENS; newMintEntity.ENS = ENS;
newMintEntity.commitHash = commitHash; newMintEntity.commitHash = commitHash;
newMintEntity.gitRepository = gitRepository; newMintEntity.gitRepository = gitRepository;
newMintEntity.ipfsHash = ipfsHash;
newMintEntity.logo = logo; newMintEntity.logo = logo;
newMintEntity.color = color; newMintEntity.color = color;
newMintEntity.accessPointAutoApproval = accessPointAutoApproval; newMintEntity.accessPointAutoApproval = accessPointAutoApproval;
@ -68,8 +70,6 @@ export function handleNewMint(event: NewMintEvent): void {
token.description = description; token.description = description;
token.externalURL = externalURL; token.externalURL = externalURL;
token.ENS = ENS; token.ENS = ENS;
token.gitRepository = gitRepository;
token.commitHash = commitHash;
token.logo = logo; token.logo = logo;
token.color = color; token.color = color;
token.accessPointAutoApproval = accessPointAutoApproval; token.accessPointAutoApproval = accessPointAutoApproval;

View File

@ -32,7 +32,7 @@ dataSources:
- ChangeAccessPointAutoApproval - ChangeAccessPointAutoApproval
abis: abis:
- name: FleekNFA - name: FleekNFA
file: ../contracts/deployments/goerli/FleekERC721.json file: ../contracts/artifacts/contracts/FleekERC721.sol/FleekERC721.json
eventHandlers: eventHandlers:
- event: Approval(indexed address,indexed address,indexed uint256) - event: Approval(indexed address,indexed address,indexed uint256)
handler: handleApproval handler: handleApproval
@ -41,13 +41,13 @@ dataSources:
# Token Events # Token Events
- event: MetadataUpdate(indexed uint256,string,string,indexed address) - event: MetadataUpdate(indexed uint256,string,string,indexed address)
handler: handleMetadataUpdateWithStringValue handler: handleMetadataUpdateWithStringValue
- event: MetadataUpdate(indexed uint256,string,string[2],indexed address) - event: MetadataUpdate(indexed uint256,string,string[4],indexed address)
handler: handleMetadataUpdateWithDoubleStringValue handler: handleMetadataUpdateWithMultipleStringValues
- event: MetadataUpdate(indexed uint256,string,uint24,indexed address) - event: MetadataUpdate(indexed uint256,string,uint24,indexed address)
handler: handleMetadataUpdateWithIntValue handler: handleMetadataUpdateWithIntValue
- event: MetadataUpdate(indexed uint256,string,bool,indexed address) - event: MetadataUpdate(indexed uint256,string,bool,indexed address)
handler: handleMetadataUpdateWithBooleanValue handler: handleMetadataUpdateWithBooleanValue
- event: NewMint(indexed uint256,string,string,string,string,string,string,string,uint24,bool,indexed address,indexed address,address) - event: NewMint(indexed uint256,string,string,string,string,string,string,string,string,uint24,bool,indexed address,indexed address,address)
handler: handleNewMint handler: handleNewMint
- event: Transfer(indexed address,indexed address,indexed uint256) - event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransfer handler: handleTransfer

2866
yarn.lock

File diff suppressed because it is too large Load Diff