aptos
OpenBlock loads Dapp via an iframe, and the Dapp interacts with the OpenBlock wallet using window.obaptos
tip
- use window.obaptos replace window.aptos
OpenBlock will send a message to the DApp when the Dapp is loaded. The Dapp can use this message to determine if the host application is OpenBlock and then load innerdappsdk:
// openblock side:
dappPageIframe.onload = () => {
dappPageIframe.contentWindow?.postMessage(
{
from: "openblock-content-integration",
target: 'dapp-inpage-integration',
value: 'dapploaded',
},
"*"
);
};// dapp side:
window.addEventListener(
'message',
event => {
if (event.data.target === 'dapp-inpage-integration' && event.data.from === 'openblock-content-integration') {
// fom openblock wallet
return;
}
},
false
);
Wallet Provider Methods
connect
response:
{
publicKey: string,// prefix 0x
address: string,
}
const provider = window.openblock.obaptos;
const account = await provider.connect();
console.log(account);
account
response:
{
publicKey: string,// prefix 0x
address: string,
}
const provider = window.openblock.obaptos;
const account = await provider.account();
console.log(account);
network
response:
{
api: string,// aptos node_url
name: string, // only support mainnet
chainId: number, // 1
}
const provider = window.openblock.obaptos;
const network = await provider.network();
console.log(network);
disconnect
response: <boolean>
const provider = window.openblock.obaptos;
const result = await provider.disconnect();
console.log(result);
isConnected
response: <boolean>
const provider = window.openblock.obaptos;
const result = await provider.isConnected();
console.log(result);
signAndSubmitTransaction
request : Types.EntryFunctionPayload
response:
{
hash: string, //prefix 0x
}
const provider = window.openblock.obaptos;
const payload = {
type: 'entry_function_payload',
function: '0x1::managed_coin::register',
arguments: [],
type_arguments: [
'0xe4497a32bf4a9fd5601b27661aa0b933a923191bf403bd08669ab2468d43b379::move_coin::MoveCoin',
],
};
const result = await provider.signAndSubmitTransaction(payload);
console.log(result);
signMessage
request : SignMessagePayload
{
address?: boolean; // Should we include the address of the account in the message
application?: boolean; // Should we include the domain of the dApp
chainId?: boolean; // Should we include the current chain id the wallet is connected to
message: string; // The message to be signed and displayed to the user
nonce: string; // A nonce the dApp should generate
}
response: SignMessageResponse
{
address?: string;
application?: string;
chainId?: number;
fullMessage: string; // The message that was generated to sign
message: string; // The message passed in by the user
nonce: string,
prefix: string, // Should always be APTOS
signature: string //prefix 0x
}
const provider = window.openblock.obaptos;
const signMessagePayload = {
address: true,
application: true,
chainId: true,
message: 'hello world!',
nonce: 888,
};
const signMessageResponse = await provider.signMessage(signMessagePayload);
console.log(result);
onAccountChange
const handleAccountChange = async (account) => {
if (account === undefined) {
return;
}
/* account :
{ publicKey: string,// prefix 0x
address: string,
}
*/
};
await provider.onAccountChange(handleAccountChange);
onNetworkChange
const handleNetworkChange = (network) => {
/* network :
{
api: string,// aptos node_url
name: string, // only support mainnet
chainId: number, // 1
}
*/
};
await provider.onNetworkChange(handleNetworkChange);
Source Code
inner-dappsdk.js
const DAPP_INPAGE = 'dapp-inpage-integration'
const DAPP_CONTENT = 'openblock-content-integration'
const APTOS_REQUEST_AUTH = 'aptos_requestAccounts'
const APTOS_WALLET_PROVIDER = 'obaptos'
const guid = () => {
function S4 () {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
}
return S4() + S4() + S4() + S4() + S4() + S4() + S4() + S4()
}
class openBlockInpageProvider {
constructor (walletProvider) {
console.log(`start initialize ${walletProvider} provider`)
this.walletProvider = walletProvider
this.callBackList = {}
this.eventListener = {}
this.isOpenBlock = true
this.connect = this.connect.bind(this)
this.account = this.account.bind(this)
this.network = this.network.bind(this)
this.disconnect = this.disconnect.bind(this)
this.isConnected = this.isConnected.bind(this)
this.requestId = 1
this.signAndSubmitTransaction = this.signAndSubmitTransaction.bind(this)
this.signMessage = this.signMessage.bind(this)
this.onAccountChange = this.onAccountChange.bind(this)
this.onNetworkChange = this.onNetworkChange.bind(this)
}
async account () {
const res = await this.request({ method: 'aptos_accounts' })
return res
}
async connect () {
let res = await this._hookRequest('aptos_accounts')
if (res?.publicKey) {
res.status = 200
res.isConnected = true
return new Promise(resolve => resolve(res))
}
res = this.request({ method: APTOS_REQUEST_AUTH })
return res
}
async disconnect () {
return true
}
async isConnected () {
const res = await this._hookRequest('aptos_accounts')
if (res?.address && res?.publicKey) {
return true
}
return false
}
async network () {
const res = await this._hookRequest('aptos_network')
return res
}
async signAndSubmitTransaction (params) {
const result = await this.request({
method: 'aptos_sendTransaction',
params
})
return { hash: result }
}
async signMessage (params) {
const res = await this.request({ method: 'aptos_sign', params })
res.signature = res.signature.slice(2)
return res
}
onAccountChange (cbk) {
return new Promise(async resolve => {
const res = await this._hookRequest('aptos_accounts')
cbk(res)
this.on('onAccountChange', cbk)
resolve()
})
}
onNetworkChange (cbk) {
return new Promise(async resolve => {
this.on('onNetworkChange', cbk)
const res = await this._hookRequest('aptos_network')
cbk(res)
resolve()
})
}
on (event, callback) {
if (typeof event !== 'string' || typeof callback !== 'function') {
return
}
if (this.eventListener[event] && this.eventListener[event].length > 5) {
return
} else if (this.eventListener[event]) {
this.eventListener[event].push(callback)
this.eventListener[event] = Array.from(new Set(this.eventListener[event]))
} else if (!this.eventListener[event]) {
this.eventListener = {
...this.eventListener,
[event]: [callback]
}
}
this._registerEvent(event)
}
_handleNormalMethod (mark, event) {
if (event.data.value.data?.result) {
this.callBackList[mark.id]?.['resolve'](event.data.value.data?.result)
}
if (event.data.value.data?.error) {
this.callBackList[mark.id]?.['reject'](event.data.value.data?.error)
}
delete this.callBackList[mark.id]
}
_handleEventMethod (mark, event) {
let eventName = event.data?.value?.data?.mark?.eventName
let params = event.data?.value?.data?.params
if (eventName) {
const fireList = this.eventListener[eventName]
if (!fireList) return
fireList.forEach(func => {
if (eventName === 'chainChanged') {
this.chainId = params
this.networkVersion = Number(params)
}
func(params)
})
}
}
_hookRequest (paramsObj) {
return new Promise((resolve, reject) => {
const _guid = guid()
if (typeof paramsObj === 'string') {
paramsObj = {
method: paramsObj
}
}
paramsObj = {
...paramsObj,
provider: this.walletProvider,
mark: {
id: _guid,
method: paramsObj.method,
type: 'call_method'
}
}
window.parent.postMessage(
{ from: DAPP_INPAGE, target: DAPP_CONTENT, value: paramsObj },
'*'
)
this.callBackList[_guid] = {
resolve,
reject
}
})
}
_registerEvent (event) {
let value = {
mark: {
eventName: event,
type: 'register_event'
},
eventName: event
}
console.log('0.registerEvent', event, value)
window.postMessage({ from: DAPP_INPAGE, target: DAPP_CONTENT, value }, '*')
}
}
function initializeProvider () {
if (!window[APTOS_WALLET_PROVIDER]) {
let provider = new openBlockInpageProvider(APTOS_WALLET_PROVIDER)
provider = new Proxy(provider, {
deleteProperty: () => true
})
delete window[APTOS_WALLET_PROVIDER]
Object.defineProperty(window, APTOS_WALLET_PROVIDER, {
value: provider,
configurable: false,
writable: false
})
}
}
if (typeof window !== 'undefined') {
initializeProvider()
}