Skip to content

Commit

Permalink
chore: split Init functions for storage providers in Init and setup
Browse files Browse the repository at this point in the history
  • Loading branch information
iamantonioalfonso committed Sep 26, 2024
1 parent 6e15437 commit 08846f8
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 78 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ipdw",
"version": "3.1.6",
"version": "3.1.7",
"author": "humandataincome",
"type": "module",
"main": "./dist/node/index.js",
Expand Down
60 changes: 32 additions & 28 deletions src/core/storage/algorand.storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ export class AlgorandStorageProvider implements StorageProvider {
private rwLock = new ReadWriteLock();

private account: algosdk.Account;
private readonly applicationId: bigint;
private applicationId: bigint;
private readonly client: algosdk.Algodv2;
private readonly contractName: string;

constructor(account: Account, applicationId: bigint, client: algosdk.Algodv2) {
constructor(account: Account, applicationId: bigint, contractName: string, client: algosdk.Algodv2) {
this.account = account;
this.applicationId = applicationId;
this.contractName = contractName;
this.client = client;
}

Expand All @@ -42,12 +44,6 @@ export class AlgorandStorageProvider implements StorageProvider {
const account = algosdk.mnemonicToSecretKey(algosdk.secretKeyToMnemonic(Buffer.from(privateKey.slice(2), 'hex')));
debug('ALGO Address is', account.addr);

const accountInfo = await client.accountInformation(account.addr).do();
const balance = accountInfo.amount / ALGORAND_TOKEN_UNIT;
debug('ALGO Balance is', balance);
if (balance < 4) // 0.001 ALGO just for deploy
throw Error('Keep at least 4 ALGO on the wallet');

let resApplicationId: bigint | undefined = undefined;
let nextToken: string | undefined = '';
do {
Expand All @@ -71,18 +67,28 @@ export class AlgorandStorageProvider implements StorageProvider {
nextToken = response.nextToken;
} while (nextToken);

return new AlgorandStorageProvider(account, resApplicationId!, contractName, client);
}

public async setup() {
const accountInfo = await this.client.accountInformation(this.account.addr).do();

const balance = accountInfo.amount / ALGORAND_TOKEN_UNIT;
debug('ALGO Balance is', balance);
if (balance < 4) // 0.001 ALGO just for deploy
throw Error('Keep at least 4 ALGO on the wallet');

if (resApplicationId === undefined) {
if (this.applicationId === undefined) {
const appArgs = [
new TextEncoder().encode(contractName)
new TextEncoder().encode(this.contractName)
];

const compiledApprovalProgram = await client.compile(Buffer.from(ALGORAND_STORAGE_APPROVAL_CODE, 'base64')).do();
const compiledClearProgram = await client.compile(Buffer.from(ALGORAND_STORAGE_CLEAR_CODE, 'base64')).do();
const suggestedParams = await client.getTransactionParams().do();
const compiledApprovalProgram = await this.client.compile(Buffer.from(ALGORAND_STORAGE_APPROVAL_CODE, 'base64')).do();
const compiledClearProgram = await this.client.compile(Buffer.from(ALGORAND_STORAGE_CLEAR_CODE, 'base64')).do();
const suggestedParams = await this.client.getTransactionParams().do();

const txn = algosdk.makeApplicationCreateTxnFromObject({
sender: account.addr,
sender: this.account.addr,
suggestedParams: suggestedParams,
onComplete: algosdk.OnApplicationComplete.NoOpOC,
approvalProgram: new Uint8Array(Buffer.from(compiledApprovalProgram.result, "base64")),
Expand All @@ -94,33 +100,31 @@ export class AlgorandStorageProvider implements StorageProvider {
appArgs: appArgs
});

const signedTxn = txn.signTxn(account.sk);
const {txid} = await client.sendRawTransaction(signedTxn).do();
const confirmedTxn = await algosdk.waitForConfirmation(client, txid, 4);
const signedTxn = txn.signTxn(this.account.sk);
const {txid} = await this.client.sendRawTransaction(signedTxn).do();
const confirmedTxn = await algosdk.waitForConfirmation(this.client, txid, 4);

resApplicationId = confirmedTxn.applicationIndex;
debug("Created Application ID:", resApplicationId);
this.applicationId = confirmedTxn.applicationIndex!;
debug("Created Application ID:", this.applicationId);
}

const applicationAddress = algosdk.getApplicationAddress(resApplicationId!);
const applicationAccountInfo = await client.accountInformation(applicationAddress).do();
const applicationAddress = algosdk.getApplicationAddress(this.applicationId!);
const applicationAccountInfo = await this.client.accountInformation(applicationAddress).do();
const applicationBalance = applicationAccountInfo.amount / ALGORAND_TOKEN_UNIT;
debug('Application ALGO Balance is', applicationBalance);
if (applicationBalance < 1) {
const totalCost = 3n * ALGORAND_TOKEN_UNIT;
const txn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
sender: account.addr,
sender: this.account.addr,
receiver: applicationAddress,
amount: totalCost,
suggestedParams: await client.getTransactionParams().do(),
suggestedParams: await this.client.getTransactionParams().do(),
})

const signedTxn = txn.signTxn(account.sk);
const {txid} = await client.sendRawTransaction(signedTxn).do();
await algosdk.waitForConfirmation(client, txid, 4);
const signedTxn = txn.signTxn(this.account.sk);
const {txid} = await this.client.sendRawTransaction(signedTxn).do();
await algosdk.waitForConfirmation(this.client, txid, 4);
}

return new AlgorandStorageProvider(account, resApplicationId!, client);
}

private static hashKey(key: string): Uint8Array {
Expand Down
42 changes: 24 additions & 18 deletions src/core/storage/bnbgreenfield.storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,50 +42,56 @@ export class BNBGreenfieldStorageProvider implements StorageProvider {

const address = web3.eth.accounts.privateKeyToAccount(privateKey).address;

const balance = await client.account.getAccountBalance({
address: address,
// To check buckets go to https://testnet.dcellar.io/buckets
return new BNBGreenfieldStorageProvider(privateKey, address, bucketName, primarySP.endpoint, client);
}

public async setup() {
const balance = await this.client.account.getAccountBalance({
address: this.address,
denom: 'BNB',
});

// To check buckets go to https://testnet.dcellar.io/buckets

if (BigInt(balance.balance!.amount) < 10 ** (18 - 2)) {
throw Error('Keep at least 0.01 BNB on the wallet on Greenfield network, use https://greenfield.bnbchain.org/en/bridge?type=transfer-in');
}

const quota = await client.bucket.getBucketReadQuota({
bucketName: bucketName
const quota = await this.client.bucket.getBucketReadQuota({
bucketName: this.bucketName
}, {
type: 'ECDSA',
privateKey: privateKey,
privateKey: this.privateKey,
});

if (quota.body) {
const availableQuota = (quota.body!.freeQuota - quota.body!.freeConsumedSize) + (quota.body!.readQuota - quota.body!.consumedQuota) + (quota.body!.monthlyFreeQuota - quota.body!.monthlyQuotaConsumedSize);
if (availableQuota < 1024 * 1024 * 128) { // 128 Mb
const updateBucketTx = await client.bucket.updateBucketInfo({
bucketName: bucketName,
operator: address,
const updateBucketTx = await this.client.bucket.updateBucketInfo({
bucketName: this.bucketName,
operator: this.address,
chargedReadQuota: Long.fromNumber(1024 * 1024 * 512).toString(), // 512 Mb
visibility: VisibilityType.VISIBILITY_TYPE_PRIVATE,
paymentAddress: address,
paymentAddress: this.address,
});
await BNBGreenfieldStorageProvider.SendTransaction(updateBucketTx, privateKey);
await BNBGreenfieldStorageProvider.SendTransaction(updateBucketTx, this.privateKey);
}
} else {
const createBucketTx = await client.bucket.createBucket({
bucketName: bucketName,
creator: address,
const sps = await this.client.sp.getStorageProviders();
const sortedSps = sps.sort((a, b) => a.id - b.id);
const primarySP = sortedSps[0];

const createBucketTx = await this.client.bucket.createBucket({
bucketName: this.bucketName,
creator: this.address,
visibility: VisibilityType.VISIBILITY_TYPE_PRIVATE,
chargedReadQuota: Long.fromNumber(1024 * 1024 * 512), // 512 Gb
primarySpAddress: primarySP.operatorAddress,
paymentAddress: address,
paymentAddress: this.address,
},
);
await BNBGreenfieldStorageProvider.SendTransaction(createBucketTx, privateKey);
await BNBGreenfieldStorageProvider.SendTransaction(createBucketTx, this.privateKey);
}

return new BNBGreenfieldStorageProvider(privateKey, address, bucketName, primarySP.endpoint, client);
}

private static async SendTransaction(transaction: TxResponse, privateKey: string): Promise<DeliverTxResponse> {
Expand Down
34 changes: 21 additions & 13 deletions src/core/storage/cere.storage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {DdcClient, File, FileUri, Signer} from '@cere-ddc-sdk/ddc-client';
import {CnsRecord, NodeInterface} from '@cere-ddc-sdk/ddc';
import {StorageProvider} from "./";
import {Blockchain} from "@cere-ddc-sdk/blockchain";
import {Blockchain, Cluster} from "@cere-ddc-sdk/blockchain";
import {Bucket} from "@cere-ddc-sdk/blockchain/src/types";

import Debug from "debug";
Expand All @@ -21,12 +21,16 @@ export const CERE_TOKEN_UNIT = 10_000_000_000n;
export class CereStorageProvider implements StorageProvider {
private ddcClient: DdcClient;
private ddcNode: NodeInterface;
private readonly bucketId: bigint;
private bucketId: bigint;
private cluster: Cluster;
private bucketName: string;

private constructor(ddcClient: DdcClient, ddcNode: NodeInterface, bucketId: bigint) {
private constructor(ddcClient: DdcClient, ddcNode: NodeInterface, cluster: Cluster, bucketId: bigint, bucketName: string) {
this.ddcClient = ddcClient;
this.ddcNode = ddcNode;
this.cluster = cluster;
this.bucketId = bucketId;
this.bucketName = bucketName;
}

public static async Init(privateKey: string, rpcUrl: string = CERE_MAINNET_RPC_URL, indexerUrl: string = CERE_MAINNET_INDEXER_URL, bucketName: string = CERE_DEFAULT_BUCKET_NAME): Promise<CereStorageProvider> {
Expand Down Expand Up @@ -56,24 +60,28 @@ export class CereStorageProvider implements StorageProvider {
break;
}
}
const deposit = await ddcClient.getDeposit();


return new CereStorageProvider(ddcClient, ddcNode, selectedCluster, resBucketId, bucketName);
}

public async setup() {
const deposit = await this.ddcClient.getDeposit();

if (deposit < 1n * CERE_TOKEN_UNIT) {
const balance = await ddcClient.getBalance();
const balance = await this.ddcClient.getBalance();
if (balance < 5n * CERE_TOKEN_UNIT)
throw Error('Keep at least 5 CERE on the wallet, they will be automatically deposited for storage when needed. Use https://bridge.cere.network/transfer');

await ddcClient.depositBalance(5n * CERE_TOKEN_UNIT);
await this.ddcClient.depositBalance(5n * CERE_TOKEN_UNIT);
}

if (resBucketId === 0n) {
resBucketId = await ddcClient.createBucket(selectedCluster.clusterId, {isPublic: false});
debug('Bucket created with id', resBucketId)
const bucketNameFileUri = await ddcClient.store(resBucketId, new File(new TextEncoder().encode(bucketName)))
await ddcNode.storeCnsRecord(resBucketId, new CnsRecord(bucketNameFileUri.cid, '__name__'));
if (this.bucketId === 0n) {
this.bucketId = await this.ddcClient.createBucket(this.cluster.clusterId, {isPublic: false});
debug('Bucket created with id', this.bucketId)
const bucketNameFileUri = await this.ddcClient.store(this.bucketId, new File(new TextEncoder().encode(this.bucketName)))
await this.ddcNode.storeCnsRecord(this.bucketId, new CnsRecord(bucketNameFileUri.cid, '__name__'));
}

return new CereStorageProvider(ddcClient, ddcNode, resBucketId);
}

private static async GetBucketList(indexerUrl: string, ownerId: string): Promise<any> {
Expand Down
20 changes: 14 additions & 6 deletions test/algorand.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@ import {ALGORAND_TESTNET_INDEXER_URL, ALGORAND_TESTNET_SERVER_URL, AlgorandStora
async function main(): Promise<void> {
const provider = await AlgorandStorageProvider.Init('0xb577c4367d79f1a7a0c8353f7937d601758d92c35df958781d72d70f9177e52f', ALGORAND_TESTNET_SERVER_URL, ALGORAND_TESTNET_INDEXER_URL);

console.log('set', await provider.set("myKey", new TextEncoder().encode("myValue")))
console.log('get', new TextDecoder().decode(await provider.get("myKey")));
console.log('has', await provider.has("myKey"));
console.log('ls', await provider.ls());
console.log('clear', await provider.clear());
console.log('has not', await provider.has("myKey"));
try {
await provider.setup();

console.log('set', await provider.set("myKey", new TextEncoder().encode("myValue")))
console.log('get', new TextDecoder().decode(await provider.get("myKey")));
console.log('has', await provider.has("myKey"));
console.log('ls', await provider.ls());
console.log('clear', await provider.clear());
console.log('has not', await provider.has("myKey"));
} catch (e) {
console.log(e);

console.log('getAccountInfo', await provider.getAccountInfo())
}
}

main()
Expand Down
21 changes: 15 additions & 6 deletions test/bnbgreenfield.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,21 @@ import {BNBGreenfieldStorageProvider, GREENFIELD_TESTNET_CHAIN_ID, GREENFIELD_TE
async function main(): Promise<void> {
const provider = await BNBGreenfieldStorageProvider.Init('0xb577c4367d79f1a7a0c8353f7937d601758d92c35df958781d72d70f9177e52f', GREENFIELD_TESTNET_CHAIN_RPC_URL, GREENFIELD_TESTNET_CHAIN_ID);

console.log('set', await provider.set("myKey", new TextEncoder().encode("myValue")))
console.log('get', new TextDecoder().decode(await provider.get("myKey")));
console.log('has', await provider.has("myKey"));
console.log('ls', await provider.ls());
console.log('clear', await provider.clear());
console.log('has not', await provider.has("myKey"));
try {
await provider.setup();

console.log('set', await provider.set("myKey", new TextEncoder().encode("myValue")))
console.log('get', new TextDecoder().decode(await provider.get("myKey")));
console.log('has', await provider.has("myKey"));
console.log('ls', await provider.ls());
console.log('clear', await provider.clear());
console.log('has not', await provider.has("myKey"));
} catch (e) {
console.error(e);

console.log('getAccountInfo', await provider.getAccountInfo())
}

}

main()
Expand Down
21 changes: 15 additions & 6 deletions test/cere.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,21 @@ import {CERE_TESTNET_INDEXER_URL, CERE_TESTNET_RPC_URL, CereStorageProvider} fro
async function main(): Promise<void> {
const provider = await CereStorageProvider.Init('hybrid label reunion only dawn maze asset draft cousin height flock nation', CERE_TESTNET_RPC_URL, CERE_TESTNET_INDEXER_URL);

console.log('set', await provider.set("myKey", new TextEncoder().encode("myValue")))
console.log('get', new TextDecoder().decode(await provider.get("myKey")));
console.log('has', await provider.has("myKey"));
console.log('ls', await provider.ls());
console.log('clear', await provider.clear());
console.log('has not', await provider.has("myKey"));
try {
await provider.setup();

console.log('set', await provider.set("myKey", new TextEncoder().encode("myValue")))
console.log('get', new TextDecoder().decode(await provider.get("myKey")));
console.log('has', await provider.has("myKey"));
console.log('ls', await provider.ls());
console.log('clear', await provider.clear());
console.log('has not', await provider.has("myKey"));
} catch (e) {
console.error(e);

console.log('getAccountInfo', await provider.getAccountInfo())
}

}

main()
Expand Down

0 comments on commit 08846f8

Please sign in to comment.