Open devchenyan opened 1 year ago
In previous nexus design, it have these methods:
wallet_fullOwnership_getOffChainLocks
Get the off chain locks. The addresses parsed from locks are for receiving assets.
Like this in neuron.
wallet_fullOwnership_getOnChainLocks
and wallet_fullOwnership_getLiveCells
Get the on chain locks. This method can make app easy to retrieve the transaction history. @zhangyouxin What the different between these two API?
wallet_fullOwnership_signData
Sign a data with a special private key. This method is for signing a message.
ckb_getBlockchainInfo
Get the blockchain info
ckb_sendTransaction
Send the transaction to blockchain. will auto inject fee and sign transaction. It is a smart method for unsigned transaction.
networkChanged
Trigger when user change network on the UI.
I think these methods can be implemented the methods in wallet connect. But fullOwnership
prefix can be removed because we have to need to distinguish the ownership.
First, I propose the chains config.
With CAIP-2. It have two parts, namespace and references. ${namespace}:${references}
For convenient, the chain should be ckb
. Siting this CKB docs, it have three parameter to --chain
of ckb binary: mainnet
, testnet
and dev
.
I provide two Chain types, with and without net
suffix.
So the final chains is:
type Chains: 'mainnet' | 'testnet' | 'devnet'
// Or just remove all net suffix
type Chains = 'main' | 'test' | 'dev'
wallet_fullOwnership_getOnChainLocks
returns used locks, and wallet_fullOwnership_getLiveCells
returns their on-chain live cells.
I think we don't need to return locks or cells for DApp in neuron, just return addresses is enough, the Dapp like .bit will get cells using one of the addresses neuron has approved. And neuron can switch address with emitting address_changed
event, DApp should listen to this event and do address change business.
Here is an assumpsion(maybe a fact):
inspired by poc by homura hers is a initial draft of proposal:
m/44'/309'/0'
with SECP256K1_BLAKE160 locks (for both external and internal addresses)m/44'/309'/0'
with OMNI locks with owner mode (considering some dapps already uses this lock)Transaction
type of @ckb-lumos/base
On Wallet connect, neuron user can select multiple addresses to add to approved list, but return only one address a time, when neuron user switch to another approved address, dapp will receive a address_changed
event and do something for change address business(get balance, etc).
chains: ckb:1:1 for m/44'/309'/0' with SECP256K1_BLAKE160 locks (for both external and internal addresses) ckb:1:2 for m/44'/309'/0' with OMNI locks with owner mode (considering some dapps already uses this lock) // more chains to be added
chains: string[]; // your supported chains in CAIP-2 format e.g. ["eip155:1", "eip155:2", ...]
is these the chains in namespace? I think the chains is to distinguish which chain current wallet uses instead of different lock.
I found in EIP, there are these chain id: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md#list-of-chain-ids
CHAIN_ID |
Chain(s) |
---|---|
1 | Ethereum mainnet |
2 | Morden (disused), Expanse mainnet |
3 | Ropsten |
4 | Rinkeby |
5 | Goerli |
42 | Kovan |
1337 | Geth private chains (default) |
mainnet, Ropsten, Rinkeby are different network.
You are right, network infomation should also be involved in chain-id, and the reference part of chain-id should be coded to [-_a-zA-Z0-9]{1,32}
to be compatible with caip-2 format
Maybe we don't need address_sign_in
and address_sign_out
Because there a session_delete
event.
After connecting the Neuron wallet, the address given to the DApp is derived from the pubKey
of the secp256k1_blake160 lock
at the path m'/44'/309'/0'
. However, maybe it's not very good that the wallet only support the secp256k1_blake160 lock
. Otherwise, the DApp may face a lot of limitations. For example, Dotbit has deployed its own lock: https://explorer.nervos.org/transaction/0x489ec335355d028488de248f04520103ac361a61cc606b17d30f71c707405eb2.
So, how can we support other locks besides secp256k1_blake160
?
Initially, I thought of including lock information in the chainId, such as ckb:mainnet-bip44-secp256k1_blake160
. However, the problem with this approach is that it becomes difficult to add new locks. Is it possible that the "address" returned after connecting the Neuron wallet is actually a pubKey
? If that's the case, DApp developers can use the pubKey
to generate an address
with the lock they prefer to use.
support any lock
It seems meaningless to support any lock, because for an unknown lock, Neuron
maybe not know how to sign and can't show the assets, then what is the meaning of its existence? To get information from a local node?
support any lock
It seems meaningless to support any lock, because for an unknown lock,
Neuron
maybe not know how to sign and can't show the assets, then what is the meaning of its existence? To get information from a local node?
I've thought about this question, in signing transacion, the DApp should tell wallet which lock to sign by passing the codeHash
to wallet before really calling sign transaction, to achive that, wallet needs to provide some interfaces:
the wallet_signTransaction
will sign the inputs of tx which has the lock with codeHash
in approved list, secp256k1 codeHash is by default approved by all sites.
delare const myCodeHash: string;
const approved = await neuron.request({ method: "wallet_isContractApproved", params: [myCodeHash] });
if (!approved) {
await neuron.request({ method: "wallet_approveContract", params: [myCodeHash] });
}
await neuron.request({ method: "wallet_signTransaction", params: { tx } });
I've thought about this question, in signing transacion, the DApp should tell wallet which lock to sign by passing the
codeHash
to wallet before really calling sign transaction, to achive that, wallet needs to provide some interfaces:
- wallet_approveContract(codeHash: Hash)
- wallet_isContractApproved(codeHash: Hash)
- wallet_signTransaction(tx: Transaction)
the
wallet_signTransaction
will sign the inputs of tx which has the lock withcodeHash
in approved list, secp256k1 codeHash is by default approved by all sites.delare const myCodeHash: string; const approved = await neuron.request({ method: "wallet_isContractApproved", params: [myCodeHash] }); if (!approved) { await neuron.request({ method: "wallet_approveContract", params: [myCodeHash] }); } await neuron.request({ method: "wallet_signTransaction", params: { tx } });
Maybe we can throw an exception when calling signTransaction
with an unknown lock or type. Because developers should know which codeHash
is supported in Neuron
. And if they want us to support other codeHash
, they can propose a requirement. Or we can give a parameter to support skip signing for unknown lock
or type
, I'm not sure if this is reasonable.
FYI, a historical RFC draft: https://talk.nervos.org/t/rfc-wallet-authorization-spec-proposal/4962
FYI how keypering handled arbitrary scripts: https://nervosnetwork.github.io/keypering/#/manual?id=lock-plug-ins
FYI how keypering handled arbitrary scripts: https://nervosnetwork.github.io/keypering/#/manual?id=lock-plug-ins
sign(context: SignContext, rawTx: RawTransaction, config: Config): Promise<RawTransaction>;
export enum SignatureAlgorithm {
secp256k1 = "secp256k1",
secp256r1 = "secp256r1",
schnorr = "schnorr",
}
Seems the custom lock should provide a method for mapping unsigned transaction to a witness. (The generated witness are in it's output transaction)
And the sign algorithm is limited on several presets, for example, sign the message with secp256k1
algorithm and private key.
FYI how keypering handled arbitrary scripts: nervosnetwork.github.io/keypering/#/manual?id=lock-plug-ins
sign(context: SignContext, rawTx: RawTransaction, config: Config): Promise<RawTransaction>; export enum SignatureAlgorithm { secp256k1 = "secp256k1", secp256r1 = "secp256r1", schnorr = "schnorr", }
Seems the custom lock should provide a method for mapping unsigned transaction to a witness. (The generated witness are in it's output transaction) And the sign algorithm is limited on several presets, for example, sign the message with
secp256k1
algorithm and private key.
Correct.
The plugged-in lock script
should inform wallet
how to sign a transaction, or to say, the algorithm is injected into the wallet. But the curve to sign a message is limited to the built-in preset.
I made a simple proposal, but posting it here may slow down the issue rendering, so I post it on the HackMD for now, and I'll move it here if you think it is necessary to migrate it over for discussion
accountAddress
is used in account section, it's confusing because account
and address
are different concepts at different levels. I would suggest renaming accountAddress
to identity
Final draft is available at https://github.com/Magickbase/neuron-public-issues/blob/b0b9ddacc8daf9286da1d44d83fbfca73c9498a1/Neuron-PRDs/WalletConnect/GeneralComponent.md and https://github.com/Magickbase/neuron-public-issues/blob/b0b9ddacc8daf9286da1d44d83fbfca73c9498a1/Neuron-PRDs/WalletConnect/FAQ_cn.md
Hold on to the implementation based on wallet connect because there's a new protocol for these scenarios
Table of Contents
Namepaces
Here is an example of a session approval message, passing the namespace.
chains
In CAIP-2, ageneral blockchain identification schema is defined. This is the implementation of CAIP-2 for the CKB network.
accounts
For context, see the CAIP-10 specification.
methods
ckb_getAddresses
Get the active address list by specific lock script types
Parameters
Returns
ckb_generateAddresses
Allow a cold wallet to authorize dapps to generate addresses.
For context, see the doc
Parameters
Returns
ckb_signTransaction
Get a transaction over the provided instructions.
Parameters
Returns
ckb_signMessage
Get a signature for the provided message from the requested signer address.
Parameters
Returns
events
accountChanged
Emit the event when the account changed
addressesChanged
Emit the event when addresses changed
chainChanged
Emit the event when the chain changed