工具
https://github.com/EOSEssentials/EOSDrops
稍后补充
最近有小伙伴要做App钱包Dapp运行相关的,以及浏览器扩展,所以做点简单的介绍
由于Scatter发展较早,以及各方钱包的大力支持,Scatter已经是Dapp运行的标准了,所以这块就是兼容(伪装)Scatter协议。
对于Scatter的协议的支持,就是让三方使用Scatter.js的网页,能够无缝的运行起来(需要签名时,对其数据正确签名)
对于Scatter.js来说,支持浏览器扩展和ScatterDesktop(ws)两个版本,各种原因,Scatter浏览器扩展官方已经明确废弃,不再更新了,且引导到桌面版本。但对于App来说,我们希望的是当前的App直接使用嵌入的WebView直接打开三方的Dapp,并不需要与三方的通信或者ws(三方跳转可以参考UAL for EOSIO)
类似UAL的方式,可以把图中EOSJS改成Scatter.js
我们先以App端为例,对于一个没有接触过EOS这块的同学,我们把测试工作细分下,尽量避免区块链相关枯燥的知识。
此时可以点击
测试Scatter扩展版本与Demo Dapp交互正确。
上面保证了Demo Dapp与 Scatter扩展的交互正确了,但我们需要的接管扩展。也就是我们要伪装一个Scatter对象,
参考项目 (Scatter javascript warpper for webview)
简单来说就是我们在App中的WebView中注入一个js,并创建一个Scatter对象,并撒谎告诉Demo Dapp Scatter的浏览器扩展已经安装好了
inyIdentitys.initEOS("\(account)", "\(publicKey)");
const scatter = new TinyScatter();
scatter.loadPlugin(new TinyEOS());
window.scatter = scatter;
document.dispatchEvent(new CustomEvent('scatterLoaded'));
此时Demo Dapp会去当前的Content页面中找到我们伪装的Scatter对象,并与伪装Scatter接口交互数据。
我们伪装的Scatter收到数据后,把传入的数据发给WebView外边的钱包App,
比如交易签名,Demo Dapp会把需要签名的数据塞给伪装的Scatter的接口requestSignature
,然后伪装的Scatter会把这些数据,暗度陈仓给Webview外边的钱包App,App选用对应的私钥签名后,将数据返回给伪装的Scatter,并返回Demo Dapp。Demo Dapp拿到签名后的数据后,继续后续的操作。
当WebView打开Demo Dapp,点击,会伪装的Scatter会拦截相关请求,比如签名,当Scatter把需要签名的数据返给外边的App,App用对应的私钥签名后,返回给伪装Scatter,能够完成与 Scatter扩展版本与Demo Dapp一样的交互.
UAL for EOSIO Reference Authenticator
https://github.com/xuewuli/Tiny.Scatter
https://github.com/EOSIO/eosio-reference-chrome-extension-authenticator-app
https://github.com/EOSIO/ual-eosio-reference-authenticator
通过code获取scope
./cleos get scope eosio.token -t accounts -l 4
{
"rows": [{
"code": "eosio.token",
"scope": "a11111111111",
"table": "accounts",
"payer": "eosio",
"count": 1
},{
"code": "eosio.token",
"scope": "a123",
"table": "accounts",
"payer": "eosio",
"count": 1
},{
"code": "eosio.token",
"scope": "a22222222222",
"table": "accounts",
"payer": "eosio",
"count": 1
},{
"code": "eosio.token",
"scope": "a33333333333",
"table": "accounts",
"payer": "eosio",
"count": 1
}
],
"more": true
}
https://developers.eos.io/eosio-nodeos/v1.6.0/reference#get_table_by_scope
https://github.com/EOSIO/eos/pull/5486
轮询节点,返回不可逆区块信息再提示成功,具体技术过程如下:
目前基于EOS搭建的链,由于修改了默认的系统代币符号,所以js库这边也要做对应的修改
为了方便讲解,我们假设修改版与原版的对比数据如下
链 | 平台币符号 | 系统名 | 公钥前缀 | js库名 | ecc库名 |
---|---|---|---|---|---|
EOS原版 | EOS | eosio | EOS | eosjs | eosjs-ecc |
修改版 | BSC | bscio | BSC | bscjs | bscjs-ecc |
eosjs
版本:20.0 release
https://github.com/EOSIO/eosjs/tree/20.0.0
eosjs-ecc
版本:最新release
https://github.com/EOSIO/eosjs-ecc
export function stringToPublicKey(s: string): Key {
if (typeof s !== 'string') {
throw new Error('expected string containing public key');
}
if (s.substr(0, 3) === 'EOS') { // 中的EOS修改为自己的代币符号 BSC
const whole = base58ToBinary(publicKeyDataSize + 4, s.substr(3));
export function convertLegacyPublicKey(s: string) {
if (s.substr(0, 3) === 'EOS') { // 中的EOS修改为自己的代币符号 BSC
return publicKeyToString(stringToPublicKey(s));
}
return s;
}
"name": "eosjs"// 修改为 bscjs
"eosjs-ecc": "4.0.4", // 修改为 bscjs-ecc
declare module "eosjs-ecc"; // 修改为 bscjs-ecc
import * as ecc from 'eosjs-ecc'; // 修改为 bscjs-ecc
export function supportedAbiVersion(version: string) {
return version.startsWith('eosio::abi/1.'); // eosio修改为 bscio
}
import * as ecc from 'eosjs-ecc';
此时已经将eosjs修改为了我们的bscjs,下面我们在处理下依赖的ecc包
原本想不修改ecc,直接内部指定pubkey_prefix,但是
由于src\eosjs-jssig.ts 中
https://github.com/EOSIO/eosjs/blob/849c03992e6ce3cb4b6a11bf18ab17b62136e5c9/src/eosjs-jssig.ts#L21
const pub = convertLegacyPublicKey(ecc.PrivateKey.fromString(k).toPublic().toString());
使用了 toPublic,
https://github.com/EOSIO/eosjs-ecc/blob/2063257e8d02e82ce4ca1d0fdadf451281b33d1e/src/key_private.js#L62
function toPublic() {
if (public_key) {
// cache
// S L O W in the browser
return public_key
}
const Q = secp256k1.G.multiply(d);
return public_key = PublicKey.fromPoint(Q);
}
而这个函数里,又没有参数可以指定 自定义的 pubkey_prefix
https://github.com/EOSIO/eosjs-ecc/blob/2063257e8d02e82ce4ca1d0fdadf451281b33d1e/src/key_public.js#L18
function PublicKey(Q, pubkey_prefix = 'EOS') {
所以eosjs-ecc 还是得改下默认的平台币符号
已经提交issue(github)
开始修改默认的代币符号
privateToPublic: (wif, pubkey_prefix = 'EOS') => // 中的EOS修改为自己的代币符号 BSC
PrivateKey(wif).toPublic().toString(pubkey_prefix),
/**
@arg {pubkey} pubkey - like EOSKey..
@arg {string} [pubkey_prefix = 'EOS']
@return {boolean} valid
@example ecc.isValidPublic(pubkey) === true
*/
isValidPublic: (pubkey, pubkey_prefix = 'EOS') => // 中的EOS修改为自己的代币符号 BSC
PublicKey.isValid(pubkey, pubkey_prefix),
assert.equal(pub.toString(), 'EOS859gxfnXyUriMgUeThh1fWv3oqcpLFyHa3TfFYC4PK2HqhToVM', pubError)
修改下前缀 EOS为BSC 不然推npmjs时验证不通过
以下pubkey_prefix都改成BSC
function PublicKey(Q, pubkey_prefix = 'EOS') {
function toString(pubkey_prefix = 'EOS') {
PublicKey.isValid = function(pubkey, pubkey_prefix = 'EOS') {
PublicKey.fromString = function(public_key, pubkey_prefix = 'EOS') {
PublicKey.fromStringOrThrow = function(public_key, pubkey_prefix = 'EOS') {
describe('secp256k1 keys', () => {
it('randomKey', function() {
this.timeout(1100)
return PrivateKey.randomKey()
})
it('private to public', () => {
assert.equal(
pub.toString(),
// 'PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63',
'EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV', // 前缀改为 BSC
'pub.toString'
)
})
"name": "eosjs-ecc", // 修改为 bscjs-cc
下面内容中的eosjs-ecc 都替换成 bscjs-ecc
"build_browser": "mkdir -p lib && browserify -o lib/eosjs-ecc.js -s eosjs_ecc lib/index.js",
"build_browser_test": "yarn build && browserify -o dist/test.js lib/*.test.js",
"documentation": "node_modules/documentation/bin/documentation.js",
"minimize": "terser lib/eosjs-ecc.js -o lib/eosjs-ecc.min.js --source-map --compress --mangle",
"docs": "yarn documentation -- readme src/api_common.js --section \"Common API\" --shallow",
"srisum": "npx srisum lib/eosjs-ecc.*",
"prepublishOnly": "yarn build && yarn minimize && yarn test_lib && yarn docs && yarn srisum"
},
"repository": {
"type": "git",
"url": "git://github.com/EOSIO/eosjs-ecc.git"
},
it('privateToPublic', () => {
// const pub = 'PUB_K1_859gxfnXyUriMgUeThh1fWv3oqcpLFyHa3TfFYC4PK2Ht7beeX'
const pub = 'EOS859gxfnXyUriMgUeThh1fWv3oqcpLFyHa3TfFYC4PK2HqhToVM' // 前缀改BSC
assert.equal(ecc.privateToPublic(wif), pub)
})
it('isValidPublic', () => {
const keys = [
[true, 'PUB_K1_859gxfnXyUriMgUeThh1fWv3oqcpLFyHa3TfFYC4PK2Ht7beeX'],
[true, 'EOS859gxfnXyUriMgUeThh1fWv3oqcpLFyHa3TfFYC4PK2HqhToVM'], // 前缀改BSC
[false, 'MMM859gxfnXyUriMgUeThh1fWv3oqcpLFyHa3TfFYC4PK2HqhToVM'],
[false, 'EOS859gxfnXyUriMgUeThh1fWv3oqcpLFyHa3TfFYC4PK2HqhToVm', 'EOS'], // 前缀改BSC
[true, 'PUB859gxfnXyUriMgUeThh1fWv3oqcpLFyHa3TfFYC4PK2HqhToVM', 'PUB'],
[false, 'PUB859gxfnXyUriMgUeThh1fWv3oqcpLFyHa3TfFYC4PK2HqhToVm', 'PUB'],
]
然后参考https://www.bcskill.com/index.php/archives/437.html 将 bscjs-ecc 提交到npmjs,即可编译bscjs
npm i 或 yarn install // 安装依赖
npm run build // 编译
npm publish // 提交npmjs
npm i 或 yarn install // 安装依赖
yarn build-web // 编译web使用
此时会在 eosjs\dist-web 生成
<html>
<head>
<meta charset="utf-8">
<script src='dist-web/eosjs-api.js'></script>
<script src='dist-web/eosjs-jsonrpc.js'></script>
<script src='dist-web/eosjs-jssig.js'></script>
<script>
let pre = document.getElementsByTagName('pre')[0];
const defaultPrivateKey = "xxx"; // 私钥
const rpc = new eosjs_jsonrpc.JsonRpc('https://xxx.com'); // RPC 地址
const signatureProvider = new eosjs_jssig.JsSignatureProvider([defaultPrivateKey]);
const api = new eosjs_api.Api({ rpc, signatureProvider });
(async () => {
try {
console.log(await rpc.get_account('bcskillsurou')); // 测试账号
const result = await api.transact({
actions: [{
account: 'bscio',
name: 'buyrambytes',
authorization: [{
actor: 'bcskillsurou',
permission: 'active',
}],
data: {
payer: 'bcskillsurou',
receiver: 'bcskillsurou',
kbytes: 8192
},
}]
}, {
blocksBehind: 3,
expireSeconds: 30,
});
console.log('\n\nTransaction pushed!\n\n' + JSON.stringify(result, null, 2));
//pre.textContent += '\n\nTransaction pushed!\n\n' + JSON.stringify(result, null, 2);
} catch (e) {
console.log( '\nCaught exception: ' + e);
if (e instanceof eosjs_jsonrpc.RpcError)
console.log( '\n\n' + JSON.stringify(e.json, null, 2));
}
})();
</script>
</head>
<body>
<pre style="width: 100%; height: 100%; margin:0px; "></pre>
<pre style="width: 100%; height: 100%; margin:0px; "></pre>
</body>
</html>
https://eosio.github.io/eosjs/
https://eosio.github.io/eosjs/guides/2.-Transaction-Examples.html