Skip to content

Commit

Permalink
update blade to 10.2 and handle blade's unique ways to connect
Browse files Browse the repository at this point in the history
  • Loading branch information
a-ridley committed Jun 10, 2023
1 parent b866259 commit e884cfd
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 26 deletions.
2 changes: 1 addition & 1 deletion template.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"@types/node": "16.18.31",
"@types/react": "18.2.6",
"@types/react-dom": "18.2.4",
"@bladelabs/blade-web3.js": "0.9.14",
"@bladelabs/blade-web3.js": "0.10.2",
"@emotion/react": "11.11.0",
"@emotion/styled": "11.11.0",
"@hashgraph/sdk": "2.25.0",
Expand Down
108 changes: 83 additions & 25 deletions template/src/services/wallets/blade/bladeClient.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BladeSigner, HederaNetwork } from "@bladelabs/blade-web3.js";
import { AccountId, ContractExecuteTransaction, ContractId, TokenAssociateTransaction, TokenId, TransferTransaction } from "@hashgraph/sdk";
import EventEmitter from "events";
import { useCallback, useContext, useEffect, useState } from "react";
import { BladeContext } from "../../../contexts/BladeContext";
import { ContractFunctionParameterBuilder } from "../contractFunctionParameterBuilder";
Expand All @@ -14,35 +15,74 @@ const appMetadata = {
};
export const bladeSigner = new BladeSigner();

// We need an event emitter to trigger syncWithBladeSession and syncWithBladeDisconnected
// from outside of the BladeClient component.
//
// The BladeWallet.disconnect() method fires the syncDisconnect event, which triggers
// the syncWithBladeDisconnected callback in the BladeClient component.
//
// The connectToBladeWallet() function fires the syncSession event, which triggers
// the syncWithBladeSession callback in the BladeClient component.
const syncWithBladeEvent = new EventEmitter();

class BladeWallet implements WalletInterface {
async transferHBAR(toAddress: AccountId, amount: number) {
const transferHBARTransaction = await new TransferTransaction()
.addHbarTransfer(bladeSigner.getAccountId().toString(), -amount)
.addHbarTransfer(toAddress, amount)
.freezeWithSigner(bladeSigner);

const txResult = await transferHBARTransaction.executeWithSigner(bladeSigner);
return txResult.transactionId;
const transactionId = await transferHBARTransaction.executeWithSigner(bladeSigner)
.then(txResult => txResult.transactionId)
.catch((error) => {
console.log(error.message ? error.message : error);
return null;
});;
return transactionId;
}

async transferToken(toAddress: AccountId, tokenId: TokenId, amount: number) {
async transferFungibleToken(toAddress: AccountId, tokenId: TokenId, amount: number) {
const transferTokenTransaction = await new TransferTransaction()
.addTokenTransfer(tokenId, bladeSigner.getAccountId().toString(), -amount)
.addTokenTransfer(tokenId, toAddress, amount)
.freezeWithSigner(bladeSigner);

const txResult = await transferTokenTransaction.executeWithSigner(bladeSigner);
return txResult.transactionId;
const transactionId = await transferTokenTransaction.executeWithSigner(bladeSigner)
.then(txResult => txResult.transactionId)
.catch((error) => {
console.log(error.message ? error.message : error);
return null;
});
return transactionId;
}

async transferNonFungibleToken(toAddress: AccountId, tokenId: TokenId, serialNumber: number) {
const transferTokenTransaction = await new TransferTransaction()
.addNftTransfer(tokenId, serialNumber, bladeSigner.getAccountId().toString(), toAddress)
.freezeWithSigner(bladeSigner);

const transactionId = await transferTokenTransaction.executeWithSigner(bladeSigner)
.then(txResult => txResult.transactionId)
.catch((error) => {
console.log(error.message ? error.message : error);
return null;
});
return transactionId;
}

async associateToken(tokenId: TokenId) {
const associateTokenTransaction = await new TokenAssociateTransaction()
.setAccountId(bladeSigner.getAccountId().toString())
.setTokenIds([tokenId])
.freezeWithSigner(bladeSigner);

const txResult = await associateTokenTransaction.executeWithSigner(bladeSigner);
return txResult.transactionId;

const transactionId = await associateTokenTransaction.executeWithSigner(bladeSigner)
.then(txResult => txResult.transactionId)
.catch((error) => {
console.log(error.message ? error.message : error);
return null;
});
return transactionId;
}

// Purpose: build contract execute transaction and send to hashconnect for signing and execution
Expand All @@ -55,24 +95,31 @@ class BladeWallet implements WalletInterface {
.setFunction(functionName, functionParameters.buildHAPIParams());

const txFrozen = await tx.freezeWithSigner(bladeSigner);
await txFrozen.executeWithSigner(bladeSigner);
const transactionId = await txFrozen.executeWithSigner(bladeSigner)
.then(txResult => txResult.transactionId)
.catch((error) => {
console.log(error.message ? error.message : error);
return null;
});

// in order to read the contract call results, you will need to query the contract call's results form a mirror node using the transaction id
// after getting the contract call results, use ethers and abi.decode to decode the call_result
return txFrozen.transactionId;
return transactionId;
}
disconnect() {
bladeSigner.killSession().then(() => {
localStorage.removeItem(bladeLocalStorage);
});
syncWithBladeEvent.emit("syncDisconnect");
localStorage.removeItem(bladeLocalStorage);
};
};
export const bladeWallet = new BladeWallet();

export const connectToBladeWallet = async () => {
export const connectToBladeWallet = async (skipKillSession: boolean = false) => {
try {
// await bladeSigner.killSession(); // kill any existing session to allow pairing a new account
if (!skipKillSession) {
await bladeSigner.killSession(); // kill any existing session to allow pairing a new account
}
await bladeSigner.createSession(appMetadata);
syncWithBladeEvent.emit("syncSession");
localStorage.setItem(bladeLocalStorage, "true");
} catch (error) {
console.log(error);
Expand All @@ -86,7 +133,7 @@ export const BladeClient = () => {
const { setAccountId, setIsConnected } = useContext(BladeContext);

// sync with blade state with the context so the context is aware of connected account id
const syncWithBlade = useCallback(() => {
const syncWithBladeSession = useCallback(() => {
try {
const accountId = bladeSigner.getAccountId();
if (accountId) {
Expand All @@ -102,25 +149,36 @@ export const BladeClient = () => {
setIsConnected(false);
};
}, [setIsConnected, setAccountId]);
const syncWithBladeDisconnected = useCallback(() => {
setAccountId("");
setIsConnected(false);
}, [setIsConnected, setAccountId]);

// sync the blade state with the context
useEffect(() => {
const sessionCallback = () => {
syncWithBladeSession();
};
const disconnectCallback = () => {
syncWithBladeDisconnected();
};

if (usedBlade) {
connectToBladeWallet().then(() => {
syncWithBlade();
});
connectToBladeWallet(true);
}

bladeSigner.onAccountChanged(() => {
syncWithBlade();
});
}, [syncWithBlade, usedBlade]);
syncWithBladeEvent.on("syncSession", sessionCallback)
syncWithBladeEvent.on("syncDisconnect", disconnectCallback)

return () => {
syncWithBladeEvent.off("syncSession", sessionCallback);
syncWithBladeEvent.off("syncDisconnect", disconnectCallback)
}
}, [syncWithBladeSession, syncWithBladeDisconnected, usedBlade]);

useEffect(() => {
setUsedBlade(localStorage.getItem(bladeLocalStorage) === "true");
}, []);

return null;
};


0 comments on commit e884cfd

Please sign in to comment.