Skip to content

Commit

Permalink
Merge pull request #1617 from aeternity/feature/inline-code-to-docs
Browse files Browse the repository at this point in the history
docs: inline examples in guides
  • Loading branch information
davidyuk authored Jul 22, 2022
2 parents 6ddabfe + 3a3afc0 commit b997a4d
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 173 deletions.
94 changes: 2 additions & 92 deletions docs/guides/build-wallet.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,103 +15,13 @@ Note:
### 1. Create bridge between extension and page
First you need to create a bridge between your extension and the page. This can be done as follows:

```js
import browser from 'webextension-polyfill'
import {
BrowserRuntimeConnection, BrowserWindowMessageConnection, MESSAGE_DIRECTION, connectionProxy
} from '@aeternity/aepp-sdk'

const readyStateCheckInterval = setInterval(function () {
if (document.readyState === 'complete') {
clearInterval(readyStateCheckInterval)

const port = browser.runtime.connect()
const extConnection = new BrowserRuntimeConnection({ port })
const pageConnection = new BrowserWindowMessageConnection({
target: window,
origin: window.origin,
sendDirection: MESSAGE_DIRECTION.to_aepp,
receiveDirection: MESSAGE_DIRECTION.to_waellet
})
connectionProxy(pageConnection, extConnection)
}
}, 10)
```
https://github.com/aeternity/aepp-sdk-js/blob/32fbb8b44b08025d7abe53bdfa275893271cbf56/examples/browser/wallet-web-extension/src/content-script.js#L1-L27

### 2. Initialize `AeSdkWallet` class
Then you need to initialize `AeSdkWallet` class in your extension and subscribe for new `runtime` connections.
After the connection is established you can share the wallet details with the application.

```js
import browser from 'webextension-polyfill'
// ideally this can be configured by the users of the extension
const NODE_URL = 'https://testnet.aeternity.io'
const COMPILER_URL = 'https://compiler.aepps.com'
const accounts = [
new MemoryAccount({ keypair: generateKeyPair() }), // generate keypair for account1
new MemoryAccount({ keypair: generateKeyPair() }) // generate keypair for account2
]
const aeppInfo = {}

async function init () {
const aeSdk = new AeSdkWallet({
compilerUrl: COMPILER_URL,
nodes: [{ name: 'testnet', instance: new Node(NODE_URL) }],
id: browser.runtime.id,
type: WALLET_TYPE.extension,
name: 'Wallet WebExtension',
// Hook for sdk registration
onConnection (aeppId, params) {
if (!confirm(`Aepp ${params.name} with id ${aeppId} wants to connect`)) {
throw new RpcConnectionDenyError()
}
aeppInfo[aeppId] = params
},
onDisconnect (msg, client) {
console.log('Disconnect client: ', client)
},
onSubscription (aeppId) {
const { name } = aeppInfo[aeppId]
if (!confirm(`Aepp ${name} with id ${aeppId} wants to subscribe for accounts`)) {
throw new RpcRejectedByUserError()
}
},
onSign (aeppId, params) {
const { name } = aeppInfo[aeppId]
if (!confirm(`Aepp ${name} with id ${aeppId} wants to sign tx ${params.tx}`)) {
throw new RpcRejectedByUserError()
}
},
onAskAccounts (aeppId) {
const { name } = aeppInfo[aeppId]
if (!confirm(`Aepp ${name} with id ${aeppId} wants to get accounts`)) {
throw new RpcRejectedByUserError()
}
},
onMessageSign (aeppId, params) {
const { name } = aeppInfo[aeppId]
if (!confirm(`Aepp ${name} with id ${aeppId} wants to sign msg ${params.message}`)) {
throw new RpcRejectedByUserError()
}
}
})
// You can change active account using `selectAccount(address)` function
await aeSdk.addAccount(accounts[0], { select: true })
await aeSdk.addAccount(accounts[1])

chrome.runtime.onConnect.addListener(async function (port) {
// create connection
const connection = new BrowserRuntimeConnection({ port })
// add new aepp to wallet
const clientId = aeSdk.addRpcClient(connection)
// share wallet details
aeSdk.shareWalletInfo(clientId)
setInterval(() => aeSdk.shareWalletInfo(clientId), 3000)
})
}

init().then(_ => console.log('Wallet initialized!'))
```
https://github.com/aeternity/aepp-sdk-js/blob/32fbb8b44b08025d7abe53bdfa275893271cbf56/examples/browser/wallet-web-extension/src/background.js#L1-L75

## iFrame-based Wallet
The **iFrame-based** approach works similar to the **WebExtension** approach except that the `connectionProxy` in between isn't needed.
Expand Down
96 changes: 15 additions & 81 deletions docs/guides/connect-aepp-to-wallet.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,99 +7,33 @@ This guide describes the 4 steps that are necessary to connect your application
- Install [Superhero Wallet extension](https://wallet.superhero.com/) for simplicity of example.
You can build your own wallet in the next example

## 1. Specify imports and constants and state
## 1. Specify imports and constants

```js
import { AeSdkAepp, walletDetector, BrowserWindowMessageConnection, Node } from '@aeternity/aepp-sdk'

const TESTNET_NODE_URL = 'https://testnet.aeternity.io'
const MAINNET_NODE_URL = 'https://mainnet.aeternity.io'
const COMPILER_URL = 'https://compiler.aepps.com';

export default {
data: () => ({
aeSdk: null,
address: '',
balance: 0,
nodeInfo: null,
connectedAccounts: null
}),
}
```
https://github.com/aeternity/aepp-sdk-js/blob/32fbb8b44b08025d7abe53bdfa275893271cbf56/examples/browser/aepp/src/StoreAeSdkPlugin.js#L1-L5

## 2. Initialize the `AeSdkAepp` class

```js
async created () {
this.aeSdk = new AeSdkAepp({
name: 'Simple Aepp',
nodes: [
{ name: 'ae_uat', instance: new Node(TESTNET_NODE_URL) },
{ name: 'ae_mainnet', instance: new Node(MAINNET_NODE_URL) }
],
compilerUrl: COMPILER_URL,
onNetworkChange: async ({ networkId }) => {
this.aeSdk.selectNode(networkId)
this.nodeInfo = await this.aeSdk.getNodeInfo()
},
onAddressChange: async () => {
this.address = await this.aeSdk.address()
this.balance = await this.aeSdk.getBalance(this.address)
},
onDisconnect: () => {
// you may want to reset state here
alert('Disconnected')
}
})
await this.scanForWallets()
}
```

## 3. Scan for wallets
https://github.com/aeternity/aepp-sdk-js/blob/32fbb8b44b08025d7abe53bdfa275893271cbf56/examples/browser/aepp/src/StoreAeSdkPlugin.js#L34-L49

```js
methods: {
async scanForWallets() {
return new Promise((resolve) => {
const handleWallets = async function ({ wallets, newWallet }) {
newWallet = newWallet || Object.values(wallets)[0]
if (confirm(`Do you want to connect to wallet ${newWallet.name}`)) {
stopScan()
// connect to the wallet, see step 4.
await this.connect(newWallet)
resolve()
}
}
const scannerConnection = new BrowserWindowMessageConnection()
const stopScan = walletDetector(scannerConnection, handleWallets.bind(this))
})
}
}
```
## 3. Scan for wallets and connect to a wallet

## 4a. Connect to a wallet
https://github.com/aeternity/aepp-sdk-js/blob/32fbb8b44b08025d7abe53bdfa275893271cbf56/examples/browser/aepp/src/Connect.vue#L66-L85

Append method for wallet connection
Alternatively, aepp can request wallet to share node url it connected to. If agreed, then aepp can
connect to the wallet's node.

```js
async connect(wallet) {
await this.aeSdk.connectToWallet(wallet.getConnection())
this.connectedAccounts = await this.aeSdk.subscribeAddress('subscribe', 'connected')
this.address = await this.aeSdk.address()
this.balance = await this.aeSdk.getBalance(this.address).catch(() => '0')
this.nodeInfo = await this.aeSdk.getNodeInfo()
}
await this.aeSdk.connectToWallet(
wallet.getConnection(),
{ connectNode: true, name: 'wallet-node', select: true },
);
```

## 4b. Connect to a wallet and use Wallet's node for on chain communications
It can be used to

Aepps can ask the wallet to share node, if wallet supports node sharing then the Aepp can communicate with the chain using the same SDK instance.

```js
async connect (wallet) {
await this.aeSdk.connectToWallet(wallet.getConnection(), { connectNode: true, name: 'wallet-node', select: true })
}
```
- improve responsiveness by connecting to the exact node that wallet uses;
- allow to connect aepps to private/development networks without changing their configuration;
- simplify configuration on aepp side.

Note:

Expand Down
23 changes: 23 additions & 0 deletions docs/hooks.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
import os.path
import subprocess
import re
import urllib.request

def pre_build(**kwargs):
if not os.path.exists('node_modules'):
subprocess.run(['npm', 'install', '--ignore-scripts'], check=True)
subprocess.run(['npm', 'run', 'build:api'], check=True)
subprocess.run(['npm', 'run', 'docs:examples'], check=True)
subprocess.run(['npm', 'run', 'docs:api'], check=True)

def replacer(match):
filename = f'{match.group(3)}.{match.group(4)}'
url = f'https://raw.githubusercontent.com/{match.group(1)}/{match.group(2)}/{filename}'
code = urllib.request.urlopen(url).read().decode('utf-8')
extension = 'js' if match.group(4) == 'vue' else match.group(4)
return '\n'.join(
[f'``` {extension} title="{filename}"'] +
code.split('\n')[int(match.group(5)) - 1:int(match.group(6))] +
['```', f'View at [GitHub]({match.group(0)})']
)

def page_markdown(markdown, **kwargs):
return re.sub(
re.compile(
r'^https://github.com/([\w/\-]+)/blob/([0-9a-f]+)/([\w\d\-/\.]+)\.(\w+)#L(\d+)-L(\d+)$',
re.MULTILINE,
),
replacer,
markdown,
)
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins:
- mkdocs-simple-hooks:
hooks:
on_pre_build: 'docs.hooks:pre_build'
on_page_markdown: 'docs.hooks:page_markdown'
repo_url: 'https://github.com/aeternity/aepp-sdk-js'
edit_uri: ''

Expand Down

0 comments on commit b997a4d

Please sign in to comment.