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

env setup script #4

Merged
merged 94 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
e8623c5
add script to generate stubs
mezrin Sep 9, 2024
1b6dee0
add stub assets
mezrin Sep 9, 2024
588deca
temporarily deploy to s3 on pull requests
mezrin Sep 9, 2024
ed8e13e
improve tests
mezrin Sep 9, 2024
c2c67cc
add tests
mezrin Sep 9, 2024
f0ad095
fix meta of fungible tokens
mezrin Sep 9, 2024
126a8c8
add python dependency
mezrin Sep 9, 2024
40539d5
Merge remote-tracking branch 'origin/main' into add-assets
mezrin Sep 10, 2024
a35e91a
add images game a
mezrin Sep 10, 2024
6f59205
add images
mezrin Sep 10, 2024
b3cf03b
update link to images in metadata files
mezrin Sep 10, 2024
f5a8ce6
update cdn links
mezrin Sep 10, 2024
6141eea
add cover images for swords
mezrin Sep 10, 2024
4b29f09
update the docs
mezrin Sep 10, 2024
e45f457
add names for the game a
mezrin Sep 10, 2024
d249b39
add names to the game a
mezrin Sep 10, 2024
43d1a2c
add names to the game b
mezrin Sep 10, 2024
5a16f0a
add names to the game a
mezrin Sep 10, 2024
fcb2d90
add names to the game c
mezrin Sep 10, 2024
362e6ff
add names to the game c
mezrin Sep 10, 2024
3e288cc
wip
dvcpull Sep 10, 2024
d9bb381
Merge remote-tracking branch 'origin/demo-script' into add-assets
mezrin Sep 10, 2024
2a259fe
more fixese
dvcpull Sep 11, 2024
c5a6d37
typo fix
dvcpull Sep 11, 2024
390042e
Merge branch 'demo-script' into add-assets
mezrin Sep 11, 2024
550da6d
cleanup
dvcpull Sep 11, 2024
aa847a5
Merge branch 'demo-script' of github.com:traittech/trait-wallet-demo-…
dvcpull Sep 11, 2024
ab55e7f
set assets metadata
dvcpull Sep 11, 2024
e8f730d
First batch run
kehindave Sep 11, 2024
4fdbd56
use assets to generate app agents
dvcpull Sep 11, 2024
19a4680
fix images
mezrin Sep 12, 2024
9b5c54e
fix images
mezrin Sep 12, 2024
f163f5f
add TODOs
mezrin Sep 12, 2024
77531f4
Game a artifacts
kehindave Sep 12, 2024
8532dc3
Game B collection A
kehindave Sep 12, 2024
6cbb966
Game B collection B
kehindave Sep 12, 2024
ffc30b9
Revert "Game B collection B"
kehindave Sep 12, 2024
9a95a81
Game B Callection B
kehindave Sep 12, 2024
9b61f36
Game B Collection C
kehindave Sep 12, 2024
8794702
Game B Collection D
kehindave Sep 12, 2024
b0b762c
Game C Collection A
kehindave Sep 12, 2024
efa079a
Game C Collection B
kehindave Sep 12, 2024
5b502ea
Game C Collection C
kehindave Sep 12, 2024
72d69f6
Game C Collection D
kehindave Sep 12, 2024
d62ec8f
Manual modifications for balancing
kehindave Sep 12, 2024
a634717
Updated Game A
kehindave Sep 12, 2024
2054ffa
Game B
kehindave Sep 12, 2024
44147c3
Game C
kehindave Sep 12, 2024
b8e554f
openAI API
kehindave Sep 12, 2024
4858a19
cleanup and refactor
dvcpull Sep 12, 2024
d61a061
Merge branch 'demo-script' into add-assets
mezrin Sep 13, 2024
ca8dde1
fixes
dvcpull Sep 13, 2024
e372296
add upscaled game icons
mezrin Sep 13, 2024
7805f5d
fixes
mezrin Sep 13, 2024
c393286
Revert id changes
kehindave Sep 13, 2024
d6ee8f5
Merge branch 'gpt-descriptions' of https://github.com/traittech/trait…
kehindave Sep 13, 2024
659b213
Reverted title and description changes
kehindave Sep 13, 2024
ccfb645
fixes
mezrin Sep 14, 2024
cc7e8cc
Merge pull request #5 from traittech/gpt-descriptions
mezrin Sep 14, 2024
1c78f69
Merge branch 'add-assets' into demo-script
mezrin Sep 14, 2024
75bb79b
fixes
mezrin Sep 13, 2024
7bae142
wip
mezrin Sep 14, 2024
67849b4
wip
mezrin Sep 14, 2024
70341ac
wip
mezrin Sep 14, 2024
c332766
wip
mezrin Sep 15, 2024
07ed3ea
update github ci
mezrin Sep 15, 2024
289e7a3
Merge commit '07ed3ea' into demo-script
mezrin Sep 15, 2024
ad8f2b5
Merge branch 'main' into demo-script
mezrin Sep 15, 2024
4d3e3d7
add retry logic
dvcpull Sep 20, 2024
820fc5a
fixes
dvcpull Sep 20, 2024
9d20ef3
run parallel working
dvcpull Sep 20, 2024
5534192
setup free transfers
dvcpull Sep 20, 2024
1c1387b
setup decimals
dvcpull Sep 20, 2024
81d674e
setup decimals
dvcpull Sep 20, 2024
ea01498
Merge branch 'main' into demo-script
mezrin Sep 23, 2024
35c96b8
wip : common functions
dvcpull Sep 23, 2024
b0ad9ed
fix promise resolving and refactor
dvcpull Sep 24, 2024
d1bab68
cleanup
mezrin Sep 25, 2024
d01e34c
wip
mezrin Sep 25, 2024
8a94f59
unsubscribe from TX updates
mezrin Sep 25, 2024
e1922fc
change isInBlock to isFinalized
mezrin Sep 25, 2024
e40360f
seperate event scanning
dvcpull Sep 26, 2024
8e7c5c0
seperate event scanning
dvcpull Sep 26, 2024
99753ac
switch to use datagate
dvcpull Sep 27, 2024
929840f
typo fix
dvcpull Sep 27, 2024
8b37751
typo fix
dvcpull Sep 27, 2024
38045dc
fix naming actions&atomics
mezrin Sep 27, 2024
06f5025
fix naming actions&atomics
mezrin Sep 27, 2024
6126132
Merge remote-tracking branch 'origin/demo-script' into demo-script
mezrin Sep 27, 2024
03e1b04
fix naming actions&atomics, improve performance
mezrin Sep 27, 2024
92deee0
fix minting of NFTs
mezrin Sep 27, 2024
8dd9a5a
update example .env
mezrin Sep 27, 2024
6d7f3c1
do not use node subscriptions, do not send the same TX multiple times
mezrin Sep 27, 2024
01ac220
various fixes
mezrin Sep 27, 2024
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
4 changes: 3 additions & 1 deletion deploy/env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ DEMO_ACCOUNT_ONE_MNEMONIC="//Dave"
DEMO_ACCOUNT_TWO_MNEMONIC="//Eve"
DEMO_ACCOUNT_THREE_MNEMONIC="//Ferdie"

# Connection to the blockchain
WS_PROVIDER_URL="ws://127.0.0.1:52279"
DATAGATE_URL="http://127.0.0.1:18890"

# Amount to transfer to app agents
TRANSFER_AMOUNT=10
TRANSFER_AMOUNT=1000
246 changes: 142 additions & 104 deletions deploy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ const dotenv = require("dotenv");
const fs = require('fs');
const path = require('path');
const { create_app_agent } = require('./utils/app_agent');
const { create_app_agent_fungible_token } = require('./utils/fungible');
const { create_app_agent_nft_collection } = require('./utils/nft');
const { create_app_agent_nft_token } = require('./utils/nft');
const { create_fungible_tokens, set_metadata_and_mint_fungible_token, create_token_transfer } = require('./utils/fungible');
const { create_nft_collections, set_metadata_and_mint_nft, create_nft_transfers } = require('./utils/nft');
const { processSignedTransaction, processSignedBatchTransaction } = require('./utils/utils');

const startTime = Date.now();

const aws_s3_assets_path = path.join(__dirname, '..', 'aws_s3_assets');
const game_a_path = path.join(aws_s3_assets_path, 'game-a/');
Expand All @@ -18,16 +20,16 @@ const game_folders = [game_a_path, game_b_path, game_c_path];
dotenv.config();

async function main() {
// Read WS_PROVIDER_URL from .env file
console.log("Read WS_PROVIDER_URL from .env file");
const wsProviderUrl = process.env.WS_PROVIDER_URL;
if (!wsProviderUrl) {
throw new Error("WS_PROVIDER_URL is not set in the .env file");
}

// Create a provider with the URL from .env
console.log("Create a provider with the URL from .env");
const provider = new WsProvider(wsProviderUrl);

// Instantiate the API with the provider
console.log("Instantiate the API with the provider");
const api = await ApiPromise.create({
provider,
types: {
Expand All @@ -44,148 +46,184 @@ async function main() {
}
});

// Construct the keyring
console.log("Construct the keyring");
const keyring = new Keyring({ type: "sr25519" });

// Load accounts from .env file
console.log("Load accounts from .env file");
const faucetAccount = keyring.addFromUri(process.env.FAUCET_ACCOUNT_MNEMONIC);
const appAgentOne = keyring.addFromUri(process.env.APP_AGENT_OWNER_ONE_MNEMONIC);
const appAgentTwo = keyring.addFromUri(process.env.APP_AGENT_OWNER_TWO_MNEMONIC);
const appAgentThree = keyring.addFromUri(process.env.APP_AGENT_OWNER_THREE_MNEMONIC);
const appAgentOwners = [appAgentOne, appAgentTwo, appAgentThree];
const appAgentOneOwner = keyring.addFromUri(process.env.APP_AGENT_OWNER_ONE_MNEMONIC);
const appAgentTwoOwner = keyring.addFromUri(process.env.APP_AGENT_OWNER_TWO_MNEMONIC);
const appAgentThreeOwner = keyring.addFromUri(process.env.APP_AGENT_OWNER_THREE_MNEMONIC);
const appAgentOwners = [appAgentOneOwner, appAgentTwoOwner, appAgentThreeOwner];

const demo_user_one = keyring.addFromUri(process.env.DEMO_ACCOUNT_ONE_MNEMONIC);
const demo_user_two = keyring.addFromUri(process.env.DEMO_ACCOUNT_TWO_MNEMONIC);
const demo_user_three = keyring.addFromUri(process.env.DEMO_ACCOUNT_THREE_MNEMONIC);

const transferAmount = parseInt(process.env.TRANSFER_AMOUNT) * 1e12;
const demotransferAmount = parseInt(process.env.TRANSFER_AMOUNT) * 1e10;

console.log("Start to initialise the owners of the app agents");
// const transfers = [
// api.tx.balances.transferKeepAlive(appAgentOneOwner.address, transferAmount.toString()),
// api.tx.balances.transferKeepAlive(appAgentTwoOwner.address, transferAmount.toString()),
// api.tx.balances.transferKeepAlive(appAgentThreeOwner.address, transferAmount.toString()),
// api.tx.balances.transferKeepAlive(demo_user_one.address, demotransferAmount.toString()),
// api.tx.balances.transferKeepAlive(demo_user_two.address, demotransferAmount.toString()),
// api.tx.balances.transferKeepAlive(demo_user_three.address, demotransferAmount.toString()),
// ];

// console.log("Send the batch of transfers");
// await processSignedBatchTransaction(api, faucetAccount, api.tx.utility.batchAll(transfers));
// await create_balance_transfers(api, demo_user_one, demo_user_two);
// await create_balance_transfers(api, demo_user_three, demo_user_one);

console.log("Traverse the game folders and collect entity data");
const gameData = collectGameData(game_folders);

// array of fungible ids
let fungibles = [];

// array of { collectionId: collectionId, tokenId: tokenId}
let collections = [];

console.log("Starting to process game data");
for (const [gameIndex, game] of gameData.entries()) {
console.log(`Processing game ${gameIndex + 1}`);
const appAgentOwner = appAgentOwners[gameIndex];

// Create app agent and set metadata
console.log(`Creating app agent for game ${gameIndex + 1}`);
const appAgentId = await create_app_agent(api, appAgentOwner, game.appAgent.metadataUrl);
console.log(`App agent created for game ${gameIndex + 1}: ${appAgentId}`);

// Create and configure fungible tokens
if (game.fungibles.length > 0) {
console.log(`Creating fungible tokens for game ${gameIndex + 1}`);
const fungibleIds = await create_fungible_tokens(api, appAgentOwner, appAgentId, game.fungibles.length);
fungibles = [...fungibles, ...fungibleIds];
console.log(`Setting metadata and minting fungible tokens for game ${gameIndex + 1}`);
await set_metadata_and_mint_fungible_token(api, appAgentOwner, appAgentId, fungibleIds, game.fungibles.map(f => f.metadataUrl), demo_user_one, game.fungibles.map(f => f.decimals));
console.log(`Fungible tokens created and configured for game ${gameIndex + 1}`);
}

// Create a batch of transfers
const transfers = [
api.tx.balances.transferKeepAlive(appAgentOne.address, transferAmount.toString()),
api.tx.balances.transferKeepAlive(appAgentTwo.address, transferAmount.toString()),
api.tx.balances.transferKeepAlive(appAgentThree.address, transferAmount.toString())
];

// Send the batch of transfers
await new Promise((resolve, reject) => {
api.tx.utility
.batchAll(transfers)
.signAndSend(faucetAccount, ({ status, events }) => {
if (status.isInBlock || status.isFinalized) {
events.forEach(({ event }) => {
if (api.events.balances.Transfer.is(event)) {
const [from, to, amount] = event.data;
console.log(`Transferred ${amount.toNumber() / 1e12} tokens from ${from.toString()} to ${to.toString()}`);
}
});
console.log("Initial transfers completed successfully");
resolve();
}
})
.catch(reject);
});

// traverse the game folders and create app-agents and assets for each game
for (const [index, folder] of game_folders.entries()) {
console.log("folder:", folder);
let appagentId = null;
let appAgentOwner = appAgentOwners[index];

// Search for folders starting with app-agent- and print all files
const subFolders = fs.readdirSync(folder);

for (const subFolder of subFolders) {
console.log("subFolder:", subFolder);
if (subFolder.startsWith('app-agent-')) {
const folderPath = path.join(folder, subFolder);
console.log("folderPath:", folderPath);
// Create and configure NFT collections and tokens
console.log(`Creating NFT collections for game ${gameIndex + 1}`);
const collectionIds = await create_nft_collections(api, appAgentOwner, appAgentId, game.nftCollections.length);
console.log(`NFT collections created for game ${gameIndex + 1}:`, collectionIds);
for (let i = 0; i < game.nftCollections.length; i++) {
console.log(`Setting metadata and minting NFTs for collection ${collectionIds[i]} of game ${gameIndex + 1}`);
let nftInfo = await set_metadata_and_mint_nft(api, appAgentOwner, appAgentId, collectionIds[i], game.nftCollections[i], demo_user_one.address);
collections = [...collections, ...nftInfo];
}
console.log(`NFT collections created and configured for game ${gameIndex + 1}`);
}

let metadataUrl = readFilesInDirectory(folderPath);
console.log("metadataUrl:", metadataUrl);
console.log("All games processed. Fungibles:", fungibles);
console.log("Collections:", collections);

if (metadataUrl) {
appagentId = await create_app_agent(api, appAgentOwner, metadataUrl);
await new Promise(resolve => setTimeout(resolve, 10_000)); // wait for the previous tx to propogate
}
}
console.log("Create demo transfers for fungibles");
for (const fungible of fungibles) {
await create_token_transfer(api, fungible, demo_user_one, [demo_user_two, demo_user_three], 10);
await create_token_transfer(api, fungible, demo_user_two, [demo_user_one, demo_user_three], 5);
}

else if (subFolder.startsWith('fungible-')) {
console.log("fungible-token folder detected");
const folderPath = path.join(folder, subFolder);
console.log("folderPath:", folderPath);
console.log("Create demo transfers for NFTs");
for (const collection of collections) {
const recipient = Math.random() < 0.5 ? demo_user_three : demo_user_two;
await create_nft_transfers(api, collection.collectionId, collection.tokenId, demo_user_one, recipient);
}
}

let metadataUrl = readFilesInDirectory(folderPath);
console.log("metadataUrl:", metadataUrl);
create_app_agent_fungible_token(api, appAgentOwner, appagentId, demo_user_one, demo_user_two, metadataUrl);
function collectGameData(gameFolders) {
return gameFolders.map(gameFolder => {
const gameData = {
appAgent: null,
// array of { metadataUrl: metadataUrl, decimals: decimals }
fungibles: [],
// array of { metadataUrl: metadataUrl, tokens: [{ metadataUrl: metadataUrl}]}
nftCollections: []
};

await new Promise(resolve => setTimeout(resolve, 10_000)); // wait for the previous tx to propogate
}
const subFolders = fs.readdirSync(gameFolder);

if (subFolder.startsWith('nft-collection')) {
console.log("nft-collection folder detected");
const folderPath = path.join(folder, subFolder);
console.log("folderPath:", folderPath);
for (const subFolder of subFolders) {
const folderPath = path.join(gameFolder, subFolder);

if (subFolder.startsWith('app-agent-')) {
gameData.appAgent = { metadataUrl: getObjectMetadataURL(folderPath).url };
} else if (subFolder.startsWith('fungible-')) {
gameData.fungibles.push({ metadataUrl: getObjectMetadataURL(folderPath).url, decimals: getObjectMetadataURL(folderPath).decimals });
} else if (subFolder.startsWith('nft-collection')) {
const collection = { metadataUrl: null, tokens: [] };
const subsubFolders = fs.readdirSync(folderPath);

let collection_id = null;

for (const subsubFolder of subsubFolders) {
const subFolderPath = path.join(folderPath, subsubFolder);
if (subsubFolder.startsWith('nft-collection')) {
const nftCollectionPath = path.join(folderPath, subsubFolder);
console.log("nftCollectionPath:", nftCollectionPath);
let metadataUrl = readFilesInDirectory(nftCollectionPath);
console.log("metadataUrl:", metadataUrl);

collection_id = await create_app_agent_nft_collection(api, appAgentOwner, appagentId, metadataUrl);
}

else if (subsubFolder.startsWith('nft-token')) {
const nftItemPath = path.join(folderPath, subsubFolder);
console.log("nftItemPath:", nftItemPath);
let metadataUrl = readFilesInDirectory(nftItemPath);
console.log("metadataUrl:", metadataUrl);

await create_app_agent_nft_token(api, appAgentOwner, appagentId, collection_id, metadataUrl, demo_user_one, demo_user_three);
collection.metadataUrl = getObjectMetadataURL(subFolderPath).url;
} else if (subsubFolder.startsWith('nft-token')) {
collection.tokens.push({ metadataUrl: getObjectMetadataURL(subFolderPath).url });
}
}


}

else {
console.log("unknown folder detected, ignoring...");
gameData.nftCollections.push(collection);
}
}
}

return gameData;
});
}

// Function to read all files in a directory
function readFilesInDirectory(directory) {
/**
* Function searches for the json file with object metadata.
* And calculates the metadata URL based on the file path.
*
* @param {string} directory - The directory where the metadata file is stored.
* @return {string|null} The metadata URL if found, otherwise null.
*/
function getObjectMetadataURL(directory) {
const files = fs.readdirSync(directory);
const jsonFiles = files.filter(file => file.endsWith('.json'));

for (const file of jsonFiles) {
const filePath = path.join(directory, file);
const stats = fs.statSync(filePath);
if (stats.isFile()) {
console.log(`File: ${filePath}`);
const fileContent = fs.readFileSync(filePath, 'utf8');
const jsonData = JSON.parse(fileContent);
// get the decimals from the fungible metadata if it exists
let decimals = jsonData.traits.fungible ? jsonData.traits.fungible.decimals : null;

// Generate the URL based on the folder structure
const relativePath = path.relative(aws_s3_assets_path, filePath);
const url = `https://trait-wallet-demo-account.trait.tech/${relativePath.replace(/\\/g, '/')}`;

console.log(`Generated URL: ${url}`);

// Return the URL instead of reading the file content
return url;
// console.log(`Generated URL: ${url}`);
return { url, decimals };
}
}

return null;
}

async function create_balance_transfers(api, token_recipient, token_recipient_two) {
console.log("Generate free transfers between the two users");

for (let i = 0; i < 2; i++) {
let tx = api.tx.playerTransfers.submitTransferBalances(
token_recipient_two.address,
1000000
);
await processSignedTransaction(token_recipient, tx);
}
console.log(`Free transfer created and confirmed`);
}

main()
.catch(console.error)
.finally(() => process.exit());
.finally(() => {
const endTime = Date.now();
const executionTime = (endTime - startTime) / 1000; // Convert to seconds
console.log(`Total execution time: ${executionTime.toFixed(2)} seconds`);
process.exit();
});
Loading