Giter Club home page Giter Club logo

aleo-wallet-adapter's Introduction

Wallet Adapter for Aleo Apps

Modular TypeScript wallet adapters and components for Aleo applications.

This is a quick setup guide with examples of how to add Wallet Adapter to a React-based Aleo app.

Quick Setup (using React UI)

📲Install

Install these dependencies:

npm install --save \
    @demox-labs/aleo-wallet-adapter-base \
    @demox-labs/aleo-wallet-adapter-react \
    @demox-labs/aleo-wallet-adapter-reactui \
    @demox-labs/aleo-wallet-adapter-leo \
    react

🛠️Setup

import React, { FC, useMemo } from "react";
import { WalletProvider } from "@demox-labs/aleo-wallet-adapter-react";
import { WalletModalProvider } from "@demox-labs/aleo-wallet-adapter-reactui";
import { LeoWalletAdapter } from "@demox-labs/aleo-wallet-adapter-leo";
import {
  DecryptPermission,
  WalletAdapterNetwork,
} from "@demox-labs/aleo-wallet-adapter-base";

// Default styles that can be overridden by your app
require("@demox-labs/aleo-wallet-adapter-reactui/styles.css");

export const Wallet: FC = () => {
  const wallets = useMemo(
    () => [
      new LeoWalletAdapter({
        appName: "Leo Demo App",
      }),
    ],
    []
  );

  return (
    <WalletProvider
      wallets={wallets}
      decryptPermission={DecryptPermission.UponRequest}
      network={WalletAdapterNetwork.Localnet}
      autoConnect
    >
      <WalletModalProvider>
        // Your app's components go here
      </WalletModalProvider>
    </WalletProvider>
  );
};

✍🏻Signing

import { WalletNotConnectedError } from "@demox-labs/aleo-wallet-adapter-base";
import { useWallet } from "@demox-labs/aleo-wallet-adapter-react";
import { LeoWalletAdapter } from "@demox-labs/aleo-wallet-adapter-leo";
import React, { FC, useCallback } from "react";

export const SignMessage: FC = () => {
  const { wallet, publicKey } = useWallet();

  const onClick = useCallback(async () => {
    if (!publicKey) throw new WalletNotConnectedError();

    const message = "a message to sign";

    const bytes = new TextEncoder().encode(message);
    const signatureBytes = await (
      wallet?.adapter as LeoWalletAdapter
    ).signMessage(bytes);
    const signature = new TextDecoder().decode(signatureBytes);
    alert("Signed message: " + signature);
  }, [wallet, publicKey]);

  return (
    <button onClick={onClick} disabled={!publicKey}>
      Sign message
    </button>
  );
};

🔓Decrypting

import { WalletNotConnectedError } from "@demox-labs/aleo-wallet-adapter-base";
import { useWallet } from "@demox-labs/aleo-wallet-adapter-react";
import React, { FC, useCallback } from "react";

export const DecryptMessage: FC = () => {
  const { publicKey, decrypt } = useWallet();

  const onClick = async () => {
    const cipherText = "record....";
    if (!publicKey) throw new WalletNotConnectedError();
    if (decrypt) {
      const decryptedPayload = await decrypt(cipherText);
      alert("Decrypted payload: " + decryptedPayload);
    }
  };

  return (
    <button onClick={onClick} disabled={!publicKey}>
      Decrypt message
    </button>
  );
};

🗂️Requesting Records

import { WalletNotConnectedError } from "@demox-labs/aleo-wallet-adapter-base";
import { useWallet } from "@demox-labs/aleo-wallet-adapter-react";
import React, { FC, useCallback } from "react";

export const RequestRecords: FC = () => {
  const { publicKey, requestRecords } = useWallet();

  const onClick = async () => {
    const program = "credits.aleo";
    if (!publicKey) throw new WalletNotConnectedError();
    if (requestRecords) {
      const records = await requestRecords(program);
      console.log("Records: " + records);
    }
  };

  return (
    <button onClick={onClick} disabled={!publicKey}>
      Request Records
    </button>
  );
};

📡Requesting Transactions

import {
  Transaction,
  WalletAdapterNetwork,
  WalletNotConnectedError
} from "@demox-labs/aleo-wallet-adapter-base";
import { useWallet } from "@demox-labs/aleo-wallet-adapter-react";
import React, { FC, useCallback } from "react";

export const RequestTransaction: FC = () => {
  const { publicKey, requestTransaction } = useWallet();

  const onClick = async () => {
    if (!publicKey) throw new WalletNotConnectedError();

    // The record here is an output from the Requesting Records above
    const record = `'{"id":"0f27d86a-1026-4980-9816-bcdce7569aa4","program_id":"credits.aleo","microcredits":"200000","spent":false,"data":{}}'`
    // Note that the inputs must be formatted in the same order as the Aleo program function expects, otherwise it will fail
    const inputs = [JSON.parse(record), "aleo1kf3dgrz9...", `${amount}u64`];
    const fee = 35_000; // This will fail if fee is not set high enough

    const aleoTransaction = Transaction.createTransaction(
      publicKey,
      WalletAdapterNetwork.Testnet,
      'credits.aleo',
      'transfer',
      inputs,
      fee
    );

    if (requestTransaction) {
      // Returns a transaction Id, that can be used to check the status. Note this is not the on-chain transaction id
      await requestTransaction(aleoTransaction);
    }
  };

  return (
    <button onClick={onClick} disabled={!publicKey}>
      Request Transaction
    </button>
  );
};

💻Deploying Programs

import {
  Deployment,
  WalletAdapterNetwork,
  WalletNotConnectedError
} from "@demox-labs/aleo-wallet-adapter-base";
import { useWallet } from "@demox-labs/aleo-wallet-adapter-react";
import React, { FC, useCallback } from "react";

export const DeployProgram: FC = () => {
  const { publicKey, requestDeploy } = useWallet();

  const onClick = async () => {
    if (!publicKey) throw new WalletNotConnectedError();

    const program = `
      program hello.aleo;
      function main:
        input r0 as u32.public;
        input r1 as u32.private;
        add r0 r1 into r2;
        output r2 as u32.private;
    `;
    const fee = 4_835_000; // This will fail if fee is not set high enough

    const aleoDeployment = new Deployment(
      publicKey,
      WalletAdapterNetwork.Testnet,
      program,
      fee
    );

    if (requestTransaction) {
      // Returns a transaction Id, that can be used to check the status. Note this is not the on-chain transaction id
      await requestDeploy(aleoDeployment);
    }
  };

  return (
    <button onClick={onClick} disabled={!publicKey}>
      Deploy Program
    </button>
  );
};

🗂️Requesting Record Plaintexts

This requires the OnChainHistory permission

import { WalletNotConnectedError } from "@demox-labs/aleo-wallet-adapter-base";
import { useWallet } from "@demox-labs/aleo-wallet-adapter-react";
import React, { FC, useCallback } from "react";

export const RequestRecordPlaintexts: FC = () => {
  const { publicKey, requestRecordPlaintexts } = useWallet();

  const onClick = async () => {
    const program = "credits.aleo";
    if (!publicKey) throw new WalletNotConnectedError();
    if (requestRecordPlaintexts) {
      const records = await requestRecordPlaintexts(program);
      console.log("Records: " + records);
    }
  };

  return (
    <button onClick={onClick} disabled={!publicKey}>
      Request Records Plaintexts
    </button>
  );
};

🗂️Requesting Transaction History

This requires the OnChainHistory permission

import { WalletNotConnectedError } from "@demox-labs/aleo-wallet-adapter-base";
import { useWallet } from "@demox-labs/aleo-wallet-adapter-react";
import React, { FC, useCallback } from "react";

export const RequestRecords: FC = () => {
  const { publicKey, requestTransactionHistory } = useWallet();

  const onClick = async () => {
    const program = "credits.aleo";
    if (!publicKey) throw new WalletNotConnectedError();
    if (requestTransactionHistory) {
      const transactions = await requestTransactionHistory(program);
      console.log("Transactions: " + transactions);
    }
  };

  return (
    <button onClick={onClick} disabled={!publicKey}>
      Request Records Transaction History
    </button>
  );
};

Subscribing to Events

import { useWallet } from "@demox-labs/aleo-wallet-adapter-react";
import { LeoWalletAdapter } from "@demox-labs/aleo-wallet-adapter-leo";
import React, { FC, useEffect } from "react";

export const SubscribeToEvent: FC = () => {
  const { wallet } = useWallet();

  const handleAccountChange = useCallback(() => {
    // Handle account change, reconnect
  }, [wallet]);

  useEffect(() => {
    (wallet?.adapter as LeoWalletAdapter).on('accountChange', handleAccountChange);
    // Removes event listener during component teardown
    return () => {
      (wallet?.adapter as LeoWalletAdapter).off('accountChange', handleAccountChange);
    }
  }, [wallet, publicKey]);

  return (
    // Component
  );
};

aleo-wallet-adapter's People

Contributors

chirswomack avatar devstrategist avatar evanmarshall avatar fulltimemike avatar julian-demox avatar mellowcroc avatar pa-long avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aleo-wallet-adapter's Issues

[Bug] Record for transaction input may be the same as fee

🐛 Bug Report

Record for transaction input may be the same as fee,
and the execution will be fail: "Something went wrong: Found duplicate input IDs in the transaction"
20230713095524

Steps to Reproduce

  1. You have more than one credit record on your aleo account
  2. Visit: https://demo.leo.app/execute
  3. Submit a transfer, then copy the fee record in the pop-up window, and finally reject to confirmation
  4. Submit the transfer again using the copied record as input, you will find that the input is the same as the fee

Expected Behavior

Fee record will be selected from a record that is not an input.

Your Environment

  • Promgram: credits.aleo
  • Leo Wallet Version: 0.0.21

[BUG] README : Requesting Transactions Code Error

Hello, i was studying aleo wallet through aleo-wallet-adapter.
And i found some error on 'Requesting Transactions' Code, which is here.

 // The record here is an output from the Requesting Records above
    const record = `'{"id":"0f27d86a-1026-4980-9816-bcdce7569aa4","program_id":"credits.aleo","microcredits":"200000","spent":false,"data":{}}'`
    // Note that the inputs must be formatted in the same order as the Aleo program function expects, otherwise it will fail
    const inputs = [JSON.parse(record), "aleo1kf3dgrz9...", `${amount}u64`];

the way you write record is javascript string literal because of ' ' , so JSON.Parse() is not working.

So i think it is better to remove ' ' , the result would be

const record2 = {"id":"0f27d86a-1026-4980-9816-bcdce7569aa4","program_id":"credits.aleo","microcredits":"200000","spent":false,"data":{}};

Thank you!

About `transactionId`

Hello team,

I was wondering if there is a way to calculate the Aleo Transaction ID from the transactionId returned by the requestTransaction method.

Thank you and best regards.

[BUG] Record with a complex structure

Description

Hi team, i have a record like:

{
  owner: xxx.private,
  minter: xxx.private,
  prompt: [xxxu128.private, xxxu128.private, xxxu128.private],
  nonce: xxxu128.private,
  uri:  [xxxu128.private, xxxu128.private, xxxu128.private],
  _nonce: xxxgroup.public
}

But when I call requestRecords I got the following error:
image

Version

  • LeoWallet: 0.1.11

Expose the Transaction ID

Description

Just want to raise/continue the discussion here #7. From the discussion, it seems that the new functionality to return a list of transaction works but this won't work for our use case.

What would be your recommended approach if we want to track the transactions made through our platform only?

[Bug] Connect wallet with different permissions

Hi team.

If I change the connection permissions for my dapp, do I have to unlock the previous permissions in Leo Wallet?

Is it possible to change connection permissions and then override the previous permissions?

Error on getExecution(transactionId)

Hello, I am having a problem with the demox-labs/wallet-adapter library on React. The problem is with the 'getExecution' function that I get from the useWallet() hook on the adapter-react library. When I try to execute this code:

getExecution('at1gey3eeu62dtaxu4u6w6tkmuh27kt9kt92kxfzaeh6e9tnhp4rg8qz5adx9')

I get this error message:

Error:  Transaction not found.
WalletTransactionError: An unknown error occurred. Please try again or report it.

This happens with any transactionId that I pass. The transaction ids are valid when I verify them with this:
https://vm.aleo.org/api/testnet3/transaction/at1gey3eeu62dtaxu4u6w6tkmuh27kt9kt92kxfzaeh6e9tnhp4rg8qz5adx9
And transactions belong to the wallet address I'm connected with.

[Bug] requestRecords does not return output records from a correctly executed transaction

🐛 Bug Report

I have a transaction that contains 3 transitions as follow:
Screenshot 2023-07-13 at 15 58 43
and the second transition (index 1) has 4 outputs, include two credits record and two disbursement record.
but the return result of requestRecords('aleo_iou_v2_2.aleo') does not have these records.

meanwhile, i can still find that transaction in the activities.
Screenshot 2023-07-13 at 16 08 00

Steps to Reproduce

Expected Behavior

Your Environment

  • Promgram: aleo_iou_v2_2.aleo
  • Leo Wallet Version: 0.0.21

WalletNotReadyError

WalletNotReadyError
at LeoWalletAdapter.connect (adapter.ts:177:72)
at onSubmit (UserIcon.vue:18:6)
at callWithErrorHandling (runtime-core.esm-bundler.js:155:22)
at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:164:21)
at HTMLDivElement.invoker (runtime-dom.esm-bundler.js:339:9)

I encountered an error while running on Vue, 127.0.0.1 was accessed normally, but 192.168.2.7 The above error was reported

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.