Kadena
Kadena
#Overview
Kadena is a secure and scalable proof-of-work network designed to power global financial systems. It is unique in its braided multi-chain architecture, currently consisting of 20 different chains per network.
Magic interacts with the Kadena blockchain via Magic's extension NPM package @magic-ext/kadena
. The Kadena extension also lets you interact with the blockchain using methods from Kadena's Javascript SDK.
You can skip straight to our kitchen sink example directly:
👉 Kadena Example
01npm install --save @magic-ext/kadena
#Initialization
Developers can initialize the Kadena extension by providing the following config
rpcUrl
- endpoint for the Kadena nodechainId
- chain ID for the Kadena network (0 - 19)networkId
- network ID for the Kadena network
createAccountsOnChain
- this field specifies whether or not Magic will submit acreate-account
transaction as part of the new user sign up flow. Note that due to the on-chain transaction, enabling this will result in signups that take up to 30 seconds.
01import { Magic } from 'magic-sdk';
02import { KadenaExtension } from '@magic-ext/kadena';
03
04export const chainId = '0';
05export const networkId = 'testnet04';
06export const rpcUrl = `https://api.testnet.chainweb.com/chainweb/0.0/${networkId}/chain/${chainId}/pact`;
07
08
09const magic = new Magic('YOUR_API_KEY', {
10 extensions: [
11 new KadenaExtension({
12 rpcUrl,
13 chainId,
14 networkId,
15 createAccountsOnChain: true,
16 }),
17 ],
18});
#Common Methods
#SpireKey Login
Magic supports Kadena's SpireKey library, allowing users to login with just a passkey. Visit the Kadena docs to learn more about SpireKey.
01const account = magic.kadena.loginWithSpireKey();
#Get User Info
Returns information about the authenticated user, such as accountName
, publicKey
, loginType
(‘email_otp’, ‘sms’, ‘spirekey’, etc), isMfaEnabled
, email
, phoneNumber
, and spireKeyInfo
.
01const userInfo = magic.kadena.getUserInfo();
#Get Test KDA Tokens
Before you can send a transaction on the Kadena blockchain, you'll need to acquire some test KDA.
Go to our Kadena Example application
Login with your email address
Copy your Kadena account
Go to the Kadena Faucet
Paste your copied Kadena public address in the text input
Now you can use your test KDA in our example app
#Sign Transaction (with SpireKey user)
To sign a Kadena transaction for a SpireKey user, you can call the magic.kadena.signTransactionWithSpireKey()
method.
01import { addSignatures, createClient, Pact } from "@kadena/client";
02import { PactNumber } from "@kadena/pactjs";
03
04export const chainId = "0";
05export const networkId = "testnet04";
06export const rpcUrl = `https://api.testnet.chainweb.com/chainweb/0.0/${networkId}/chain/${chainId}/pact`;
07
08const handleSendTransaction = async () => {
09 const userInfo = await magic.kadena.getInfo();
10 const kadenaClient = createClient(rpcUrl);
11
12 const fromAccount = userInfo.accountName;
13 const senderPublicKey = userInfo.publicKey;
14
15 const toAccount = "k:...";
16 const receiverPublicKey = toAccount.substring(2);
17
18 const amount = new PactNumber(sendAmount).toPactDecimal();
19
20 const transaction = Pact.builder
21 .execution(
22 (Pact.modules as any).coin.transfer(fromAccount, toAccount, amount)
23 )
24 .addSigner(
25 {
26 pubKey: senderPublicKey,
27 scheme: "WebAuthn",
28 },
29 (withCapability: any) => [
30 withCapability("coin.GAS"),
31 withCapability("coin.TRANSFER", fromAccount, toAccount, amount),
32 ]
33 )
34 .addData("receiverKeyset", {
35 keys: [receiverPubKey],
36 pred: "keys-all",
37 })
38 .setMeta({ chainId, senderAccount: fromAccount })
39 .setNetworkId(networkId)
40 .createTransaction();
41
42 try {
43 const { transactions } = await magic.kadena.signTransactionWithSpireKey(
44 transaction
45 );
46 const signedTx = transactions[0];
47 const transactionDescriptor = await kadenaClient.submit(signedTx);
48 const response = await kadenaClient.listen(transactionDescriptor);
49 if (response.result.status === "failure") {
50 console.error(response.result.error);
51 } else {
52 console.log(response.result);
53 }
54 } catch (error) {
55 console.error("Failed to send transaction", error);
56 }
57};
#Sign Transaction (with non-SpireKey user)
To sign a standard Kadena transaction, you can call the magic.kadena.signTransaction()
method.
01import { addSignatures, createClient, Pact } from "@kadena/client";
02import { PactNumber } from "@kadena/pactjs";
03
04export const chainId = "0";
05export const networkId = "testnet04";
06export const rpcUrl = `https://api.testnet.chainweb.com/chainweb/0.0/${networkId}/chain/${chainId}/pact`;
07
08const handleSendTransaction = async () => {
09 const userInfo = await magic.kadena.getInfo();
10 const kadenaClient = createClient(rpcUrl);
11
12 const fromAccount = userInfo.accountName;
13 const senderPublicKey = userInfo.publicKey;
14
15 const toAccount = "k:...";
16 const receiverPublicKey = toAccount.substring(2);
17
18 const amount = new PactNumber(sendAmount).toPactDecimal();
19
20 const transaction = Pact.builder
21 .execution(
22 (Pact.modules as any).coin.transfer(fromAccount, toAccount, amount)
23 )
24 .addSigner(senderPubKey, (withCapability: any) => [
25 withCapability("coin.GAS"),
26 withCapability("coin.TRANSFER", fromAccount, toAccount, amount),
27 ])
28 .addData("receiverKeyset", {
29 keys: [receiverPubKey],
30 pred: "keys-all",
31 })
32 .setMeta({ chainId, senderAccount: fromAccount })
33 .setNetworkId(networkId)
34 .createTransaction();
35
36 try {
37 const signature = await magic.kadena.signTransaction(transaction.hash);
38 const signedTx = addSignatures(transaction, signature);
39 const transactionDescriptor = await kadenaClient.submit(signedTx);
40 const response = await kadenaClient.listen(transactionDescriptor);
41 if (response.result.status === "failure") {
42 console.error(response.result.error);
43 } else {
44 console.log(response.result);
45 }
46 } catch (error) {
47 console.error("Failed to send transaction", error);
48 }
49};