Skip to content

Commit

Permalink
Algo transaction (#149)
Browse files Browse the repository at this point in the history
* added algorand transaction and fixed spell  algo

* fixed

* fixed

* remove console

* fixed

* update

* update

* add version

Co-authored-by: Samuel@Tatum <[email protected]>
Co-authored-by: Samuel Sramko <[email protected]>
  • Loading branch information
3 people authored Sep 10, 2021
1 parent dda6883 commit 5aae3fd
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 5 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tatumio/tatum",
"version": "1.24.10",
"version": "1.25.0",
"description": "Tatum API client allows browsers and Node.js clients to interact with Tatum API.",
"main": "dist/src/index.js",
"repository": "https://github.com/tatumio/tatum-js",
Expand Down
27 changes: 27 additions & 0 deletions src/model/request/AlgoTransaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { PrivateKeyOrSignatureId } from "./PrivateKeyOrSignatureId";
import { IsNotEmpty, IsNumberString, IsOptional, Length, Matches, MaxLength, } from 'class-validator';

export class AlgoTransaction extends PrivateKeyOrSignatureId {

@IsNotEmpty()
@Length(58, 58)
public from: string;

@IsNotEmpty()
@Length(58, 58)
public to: string;

@IsNotEmpty()
@IsNumberString()
@Matches(/^[+]?((\d+(\.\d*)?)|(\.\d+))$/)
public fee: string;

@IsNotEmpty()
@IsNumberString()
@Matches(/^[+]?((\d+(\.\d*)?)|(\.\d+))$/)
public amount: string;

@IsOptional()
@MaxLength(30)
public note: string;
}
1 change: 1 addition & 0 deletions src/model/request/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,4 @@ export * from './UpdateCashbackErc721'
export * from './PrivateKeyOrSignatureIdBtcBased'
export {ContractType} from './ContractType'
export * from './egld'
export * from './AlgoTransaction'
17 changes: 17 additions & 0 deletions src/transaction/algo.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { signAlgoTransaction } from './algo'
import { AlgoTransaction } from '../model';

describe('Algo transaction', () => {
jest.setTimeout(59999)
it('should test signed transaction for Algo transfer', async () => {
const tx = new AlgoTransaction();
tx.from = 'TMETT6BXL3QUH7AH5TS6IONU7LVTLKIGG54CFCNPMQXWGRIZFIESZBYWP4';
tx.to = 'NTAESFCB3WOD7SAOL42KSPVARLB3JFA3MNX3AESWHYVT2RMYDVZI6YLG4Y';
tx.fee = '100';
tx.amount = '1000000';
tx.note = 'Helloworld';
tx.fromPrivateKey = '72TCV5BRQPBMSAFPYO3CPWVDBYWNGAYNMTW5QHENOMQF7I6QLNMJWCJZ7A3V5YKD7QD6ZZPEHG2PV2ZVVEDDO6BCRGXWIL3DIUMSUCI';
const txId = await signAlgoTransaction(true,tx, 'https://testnet-algorand.api.purestake.io/ps2');
expect(txId.length).toBe(52)
})
})
72 changes: 72 additions & 0 deletions src/transaction/algo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const algosdk = require('algosdk');
const base32 = require('base32.js');
import { TextEncoder } from 'util';
import { TATUM_API_URL } from '../constants';
import { AlgoTransaction } from '../model';

/**
*
* @param testnet if the algorand node is testnet or not
* @param provider url of the algorand server endpoint for purestake.io restapi
* @returns algorand Client
*/
export const getClient = (testnet: boolean, provider?: string) => {
const baseServer = provider || `${process.env.TATUM_API_URL || TATUM_API_URL}/v3/algorand/node`;
const token = {'X-API-Key': `${process.env.ALGO_API_KEY}`}
const algodClient = new algosdk.Algodv2(token, baseServer, '');
return algodClient;
}

/**
*
* @param algodClient algorand Client
* @param txId transaction id
* @returns confirmed result
*/
const waitForConfirmation = async (algodClient: any, txId: string) => {
let lastround = (await algodClient.status().do())['last-round'];
let limit = 0;
while (limit < 50) {
const pendingInfo = await algodClient.pendingTransactionInformation(txId).do();
if (pendingInfo['confirmed-round']) {
return true;
} else if (pendingInfo["pool-error"]) {
return false;
}
lastround++;
limit++;
await algodClient.statusAfterBlock(lastround).do();
}
return false;
}

/**
* Algorand transaction signing and confirm result
* @param testnet if the algorand node is testnet or not
* @param tx content of the transaction to broadcast
* @param provider url of the algorand server endpoint for purestake.io restapi
* @returns transaction id of the transaction in the blockchain
*/
export const signAlgoTransaction = async ( testnet: boolean, tx: AlgoTransaction, provider?: string) => {
const algodClient = getClient(testnet, provider);
const params = await algodClient.getTransactionParams().do();
const decoder = new base32.Decoder({type: "rfc4648"})
const secretKey = new Uint8Array(decoder.write(tx.fromPrivateKey).buf);
const enc = new TextEncoder();
const note = enc.encode(tx.note ? tx.note : '');
const txn = {
"from": tx.from,
"to": tx.to,
"fee": Number(tx.fee),
"amount": BigInt(tx.amount),
"firstRound": params.firstRound,
"lastRound": params.lastRound,
"genesisID": params.genesisID,
"genesisHash": params.genesisHash,
"note": note
}
const signedTxn = algosdk.signTransaction(txn, secretKey);
const sendTx = await algodClient.sendRawTransaction(signedTxn.blob).do();
const confirm = await waitForConfirmation(algodClient, sendTx.txId);
if (confirm) return sendTx.txId; else throw Error("Failed Algo Transaction Signing");
}
7 changes: 3 additions & 4 deletions src/wallet/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -651,10 +651,9 @@ const convertXdcPrivateKey = (testnet: boolean, privKey: string) => {
*/
export const generateAlgodAddressFromPrivatetKey = (privKey: string) => {
const decoder = new base32.Decoder({type: "rfc4648"})
const scretKey = decoder.write(privKey).buf;
let mn = algosdk.secretKeyToMnemonic(scretKey)
const address = algosdk.mnemonicToSecretKey(mn).addr;
return address;
const secretKey = decoder.write(privKey).buf;
const mn = algosdk.secretKeyToMnemonic(secretKey)
return algosdk.mnemonicToSecretKey(mn).addr;
}


Expand Down

0 comments on commit 5aae3fd

Please sign in to comment.