Skip to content

Commit

Permalink
add wallet connect method
Browse files Browse the repository at this point in the history
  • Loading branch information
joe-p committed Sep 12, 2023
1 parent 9660983 commit f0a5af2
Show file tree
Hide file tree
Showing 8 changed files with 379 additions and 24 deletions.
48 changes: 24 additions & 24 deletions ARCs/arc-0047.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,23 @@ All values **MUST** be validated to ensure they are encoded properly. This inclu

To enable unique identification of a description, clients **MUST** calculate the SHA256 hash of the JSON description canonicalized in accordance with <a href="https://www.rfc-editor.org/rfc/rfc8785">RFC 8785</a>.

### WalletConnect Method

For wallets to support this ARC, they need to supprt the a `algo_templatedLsig` method.

The method expects three parameters described by the interface below

```ts
interface TemplatedLsigParams {
/** The canoncalized ARC47 templated lsig JSON as described in this ARC */
arc47: string
/** The values of the templated variables, if there are any */
values?: {[variable: string]: string | number}
/** The hash of the expected program. Wallets should compile the lsig with the given values to verify the program hash matches */
hash: string
}
```

## Rationale

This provides a way for frontends to clearly display to the user what is being signed when signing a logic signature.
Expand All @@ -99,30 +116,13 @@ N/A

## Reference Implementation

### Description
```json
{
"name": "Address Opt-In",
"description": "This program allows a given address to opt-in the signer to any asset provided it's approved by the associated application",
"program": "I3ByYWdtYSB2ZXJzaW9uIDgKI2RlZmluZSBNYXN0ZXJBcHBDYWxsIGxvYWQgMAoKLy8gU2F2ZSBNYXN0ZXJBcHBDYWxsCnR4biBHcm91cEluZGV4CmludCAxCisKc3RvcmUgMAoKLy8gVmVyaWZ5IGFtb3VudCBpcyAwCnR4biBBc3NldEFtb3VudAppbnQgMAo9PQphc3NlcnQKCi8vIFZlcmlmeSBzZW5kZXIgPT0gcmVjZWl2ZXIKdHhuIEFzc2V0UmVjZWl2ZXIKdHhuIFNlbmRlcgo9PQphc3NlcnQKCi8vIFZlcmlmeSBmZWUgaXMgMCAoY292ZXJlZCBieSBzZW5kZXIpCnR4biBGZWUKaW50IDAKPT0KYXNzZXJ0CgovLyBWZXJpZnkgYXNzZXRDbG9zZVRvIGlzIG5vdCBzZXQKdHhuIEFzc2V0Q2xvc2VUbwpnbG9iYWwgWmVyb0FkZHJlc3MKPT0KYXNzZXJ0CgovLyBWZXJpZnkgY2FsbGVkIGF0b21pY2FsbHkgd2l0aCBtYXN0ZXIgYXBwCk1hc3RlckFwcENhbGwKZ3R4bnMgQXBwbGljYXRpb25JRAppbnQgVE1QTF9ERUxFR0FURURfT1BUSU5fQVBQX0lECj09CmFzc2VydAoKLy8gVmVyaWZ5IHRoZSBjb3JyZWN0IG1ldGhvZCBpcyBiZWluZyBjYWxsZWQKTWFzdGVyQXBwQ2FsbApndHhuc2EgQXBwbGljYXRpb25BcmdzIDAKbWV0aG9kICJhZGRyZXNzT3B0SW4ocGF5LGF4ZmVyKXZvaWQiCj09CmFzc2VydAoKLy8gVmVyaWZ5IHRoZSBzZW5kZXIgaXMgdGhlIGNvcnJlY3QgYWRkcmVzcwpNYXN0ZXJBcHBDYWxsCmd0eG5zIFNlbmRlcgphZGRyIFRNUExfQVVUSE9SSVpFRF9BRERSRVNTCj09",
"variables": {
[
{
"variable": "TMPL_DELEGATED_OPTIN_APP_ID",
"name": "Delegated opt-in app ID",
"type": "application",
"description": "The ID of the application that will be used for verifying opt-ins"
},
{
"variable": "TMPL_AUTHORIZED_ADDRESS",
"name": "Authorized address",
"type": "address",
"description": "The address that will be allowed to opt the signer into assets provided it's approved by the associated application"
}
]
}
}
```
A reference implementation can be found in [../assets/arc-0047](../assets/arc-0047/).

Check failure on line 119 in ARCs/arc-0047.md

View workflow job for this annotation

GitHub Actions / ARC Walidator

proposals must be referenced with the form `ARC-N` (not `arc-N`)

error[markdown-re-arc-not-arc]: proposals must be referenced with the form `ARC-N` (not `arc-N`) --> ARCs/arc-0047.md | 119 | A reference implementation can be found in [../assets/arc-0047](../assets/arc-0047/). | = info: the pattern in question: `arc[\s-]*[0-9]+`

[lsig.teal](../assets/arc-0047/lsig.teal) contains the templated TEAL code for a logic signature that allows payments of a specific amount every 25,000 blocks.

[dapp.ts](../assets/arc-0047/dapp.ts) contains a TypeScript script showcasing how a dapp would form a wallet connect request for a templated logic signature.

[wallet.ts](../assets/arc-0047/wallet.ts) contains a TypeScript script showcasing how a wallet would handle a request for signing a templated logic signature.

### String Variables

Expand Down
169 changes: 169 additions & 0 deletions assets/arc-0047/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore

# Logs

logs
_.log
npm-debug.log_
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)

report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# Runtime data

pids
_.pid
_.seed
\*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover

lib-cov

# Coverage directory used by tools like istanbul

coverage
\*.lcov

# nyc test coverage

.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)

.grunt

# Bower dependency directory (https://bower.io/)

bower_components

# node-waf configuration

.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)

build/Release

# Dependency directories

node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)

web_modules/

# TypeScript cache

\*.tsbuildinfo

# Optional npm cache directory

.npm

# Optional eslint cache

.eslintcache

# Optional stylelint cache

.stylelintcache

# Microbundle cache

.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history

.node_repl_history

# Output of 'npm pack'

\*.tgz

# Yarn Integrity file

.yarn-integrity

# dotenv environment variable files

.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)

.cache
.parcel-cache

# Next.js build output

.next
out

# Nuxt.js build / generate output

.nuxt
dist

# Gatsby files

.cache/

# Comment in the public line in if your project uses Gatsby and not Next.js

# https://nextjs.org/blog/next-9-1#public-directory-support

# public

# vuepress build output

.vuepress/dist

# vuepress v2.x temp and cache directory

.temp
.cache

# Docusaurus cache and generated files

.docusaurus

# Serverless directories

.serverless/

# FuseBox cache

.fusebox/

# DynamoDB Local files

.dynamodb/

# TernJS port file

.tern-port

# Stores VSCode versions used for testing VSCode extensions

.vscode-test

# yarn v2

.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.\*
Binary file added assets/arc-0047/bun.lockb
Binary file not shown.
49 changes: 49 additions & 0 deletions assets/arc-0047/dapp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import algosdk from 'algosdk'
import { readFileSync } from 'fs'
import {canonicalize} from 'json-canonicalize'
import { formatJsonRpcRequest } from "@json-rpc-tools/utils";
import { sha256 } from 'js-sha256';

const algodClient = new algosdk.Algodv2('a'.repeat(64), 'http://localhost', 4001)

const teal = readFileSync('./lsig.teal').toString()

const arc47 = {
name: "25000 block payment",
description: "Allows a payment to be made every 25000 blocks of a specific amount to a specific address",
program: btoa(teal),
variables: [
{
name: "Payment Amount",
variable: "TMPL_AMOUNT",
type: "uint64",
description: "Amount of the payment transaction in microAlgos"
},
{
name: "Payment Receiver",
variable: "TMPL_RECEIVER",
type: "address",
description: "Address to which the payment transaction is sent"
}
],
}

const values: Record<string, string | number> = {
TMPL_AMOUNT: 1000000,
TMPL_RECEIVER: 'Y76M3MSY6DKBRHBL7C3NNDXGS5IIMQVQVUAB6MP4XEMMGVF2QWNPL226CA'
}

let finalTeal = teal

for (const variable in values) {
finalTeal = finalTeal.replaceAll(variable, values[variable].toString())
}

const result = await algodClient.compile(finalTeal).do()

const requestParams = [canonicalize(arc47), JSON.stringify(values), result.hash]

const walletConnectRequest = formatJsonRpcRequest('algo_signTemplatedLsig', requestParams);

console.log(`Request Params: ${console.log(requestParams)}`)
console.log(`ARC47 SHA256: ${sha256(canonicalize(arc47))}`)
53 changes: 53 additions & 0 deletions assets/arc-0047/lsig.teal
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma version 9

// Verify this is a payment
txn TypeEnum
int pay
==

// Verify this is not rekeying the sender address
txn RekeyTo
global ZeroAddress
==
assert

// Verify the sender's account is not being closed
txn CloseRemainderTo
global ZeroAddress
==
assert

// Verify the receiver is equal to the templated receiver address
txn Receiver
addr TMPL_RECEIVER
==
assert

// Verify the amount is equal to the templated amount
txn Amount
int TMPL_AMOUNT
==
assert

// Verify the current round is within 500 rounds of a product of 25_000
global Round
int 25_000
%
store 0

load 0
int 500
<=

load 0
int 24_500
>=

||
assert

// Verify lease
txn Lease
byte "scheduled 25_000 payment"
sha256
==
18 changes: 18 additions & 0 deletions assets/arc-0047/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "lsig-template-example",
"module": "index.ts",
"type": "module",
"devDependencies": {
"bun-types": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
},
"dependencies": {
"@json-rpc-tools/utils": "^1.7.6",
"algosdk": "^2.5.0",
"js-sha256": "^0.10.1",
"json-canonicalize": "^1.0.6",
"tslib": "^2.6.2"
}
}
22 changes: 22 additions & 0 deletions assets/arc-0047/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"lib": ["ESNext"],
"module": "esnext",
"target": "esnext",
"moduleResolution": "bundler",
"moduleDetection": "force",
"allowImportingTsExtensions": true,
"noEmit": true,
"composite": true,
"strict": true,
"downlevelIteration": true,
"skipLibCheck": true,
"jsx": "preserve",
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"allowJs": true,
"types": [
"bun-types" // add Bun global
]
}
}
Loading

0 comments on commit f0a5af2

Please sign in to comment.