signet.js 0.0.1-beta.5 → 0.0.1-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +55 -0
- package/.prettierrc +1 -0
- package/LICENSE +19 -0
- package/README.md +42 -14
- package/babel.config.js +6 -0
- package/docs/pages/chain-signatures-contract.mdx +56 -0
- package/docs/pages/chain.mdx +45 -0
- package/docs/pages/chains/bitcoin/bitcoin.mdx +191 -0
- package/docs/pages/chains/bitcoin/btc-rpc-adapter.mdx +307 -0
- package/docs/pages/chains/cosmos.mdx +181 -0
- package/docs/pages/chains/evm.mdx +189 -0
- package/docs/pages/index.mdx +99 -0
- package/docs/snippets/contract.ts +21 -0
- package/docs/snippets/env.ts +13 -0
- package/jest.config.ts +199 -0
- package/package.json +21 -11
- package/src/chains/Bitcoin/BTCRpcAdapter/BTCRpcAdapter.ts +11 -0
- package/src/chains/Bitcoin/BTCRpcAdapter/Mempool/Mempool.ts +96 -0
- package/src/chains/Bitcoin/BTCRpcAdapter/Mempool/index.ts +1 -0
- package/src/chains/Bitcoin/BTCRpcAdapter/Mempool/types.ts +72 -0
- package/src/chains/Bitcoin/BTCRpcAdapter/index.ts +6 -0
- package/src/chains/Bitcoin/Bitcoin.ts +301 -0
- package/src/chains/Bitcoin/types.ts +45 -0
- package/src/chains/Bitcoin/utils.ts +14 -0
- package/src/chains/Chain.ts +96 -0
- package/src/chains/ChainSignatureContract.ts +48 -0
- package/src/chains/Cosmos/Cosmos.ts +279 -0
- package/src/chains/Cosmos/types.ts +35 -0
- package/src/chains/Cosmos/utils.ts +45 -0
- package/src/chains/EVM/EVM.ts +180 -0
- package/src/chains/EVM/types.ts +7 -0
- package/src/chains/EVM/utils.ts +26 -0
- package/src/chains/index.ts +34 -0
- package/src/chains/types.ts +35 -0
- package/src/chains/utils.ts +40 -0
- package/src/index.ts +2 -0
- package/src/utils/chains/index.ts +1 -0
- package/src/utils/chains/near/ChainSignatureContract.ts +195 -0
- package/src/utils/chains/near/account.ts +42 -0
- package/src/utils/chains/near/constants.ts +4 -0
- package/src/utils/chains/near/index.ts +3 -0
- package/src/utils/chains/near/relayer/index.ts +1 -0
- package/src/utils/chains/near/relayer/relayer.ts +39 -0
- package/src/utils/chains/near/relayer/types.ts +24 -0
- package/src/utils/chains/near/signAndSend/index.ts +1 -0
- package/src/utils/chains/near/signAndSend/keypair.ts +180 -0
- package/src/utils/chains/near/transactionBuilder.ts +138 -0
- package/src/utils/chains/near/types.ts +67 -0
- package/src/utils/index.ts +1 -0
- package/tsconfig.eslint.json +8 -0
- package/tsconfig.json +116 -0
- package/vite.config.ts +47 -0
- package/vocs.config.ts +60 -0
- package/src/chains/Bitcoin/BTCRpcAdapter/BTCRpcAdapter.d.ts +0 -10
- package/src/chains/Bitcoin/BTCRpcAdapter/BTCRpcAdapter.js +0 -2
- package/src/chains/Bitcoin/BTCRpcAdapter/Mempool/Mempool.d.ts +0 -15
- package/src/chains/Bitcoin/BTCRpcAdapter/Mempool/Mempool.js +0 -69
- package/src/chains/Bitcoin/BTCRpcAdapter/Mempool/index.d.ts +0 -1
- package/src/chains/Bitcoin/BTCRpcAdapter/Mempool/index.js +0 -1
- package/src/chains/Bitcoin/BTCRpcAdapter/Mempool/types.d.ts +0 -69
- package/src/chains/Bitcoin/BTCRpcAdapter/Mempool/types.js +0 -1
- package/src/chains/Bitcoin/BTCRpcAdapter/index.d.ts +0 -5
- package/src/chains/Bitcoin/BTCRpcAdapter/index.js +0 -5
- package/src/chains/Bitcoin/Bitcoin.d.ts +0 -69
- package/src/chains/Bitcoin/Bitcoin.js +0 -198
- package/src/chains/Bitcoin/types.d.ts +0 -42
- package/src/chains/Bitcoin/types.js +0 -1
- package/src/chains/Bitcoin/utils.d.ts +0 -2
- package/src/chains/Bitcoin/utils.js +0 -13
- package/src/chains/Chain.d.ts +0 -89
- package/src/chains/Chain.js +0 -9
- package/src/chains/ChainSignatureContract.d.ts +0 -62
- package/src/chains/ChainSignatureContract.js +0 -7
- package/src/chains/Cosmos/Cosmos.d.ts +0 -51
- package/src/chains/Cosmos/Cosmos.js +0 -157
- package/src/chains/Cosmos/types.d.ts +0 -30
- package/src/chains/Cosmos/types.js +0 -1
- package/src/chains/Cosmos/utils.d.ts +0 -2
- package/src/chains/Cosmos/utils.js +0 -27
- package/src/chains/EVM/EVM.d.ts +0 -42
- package/src/chains/EVM/EVM.js +0 -109
- package/src/chains/EVM/types.d.ts +0 -5
- package/src/chains/EVM/types.js +0 -1
- package/src/chains/EVM/utils.d.ts +0 -7
- package/src/chains/EVM/utils.js +0 -14
- package/src/chains/index.d.ts +0 -12
- package/src/chains/index.js +0 -12
- package/src/chains/types.d.ts +0 -31
- package/src/chains/types.js +0 -1
- package/src/chains/utils.d.ts +0 -12
- package/src/chains/utils.js +0 -27
- package/src/index.d.ts +0 -2
- package/src/index.js +0 -2
- package/src/utils/chains/index.d.ts +0 -1
- package/src/utils/chains/index.js +0 -1
- package/src/utils/chains/near/account.d.ts +0 -13
- package/src/utils/chains/near/account.js +0 -22
- package/src/utils/chains/near/constants.d.ts +0 -3
- package/src/utils/chains/near/constants.js +0 -3
- package/src/utils/chains/near/contract.d.ts +0 -40
- package/src/utils/chains/near/contract.js +0 -102
- package/src/utils/chains/near/index.d.ts +0 -3
- package/src/utils/chains/near/index.js +0 -3
- package/src/utils/chains/near/relayer/index.d.ts +0 -1
- package/src/utils/chains/near/relayer/index.js +0 -1
- package/src/utils/chains/near/relayer/relayer.d.ts +0 -8
- package/src/utils/chains/near/relayer/relayer.js +0 -33
- package/src/utils/chains/near/relayer/types.d.ts +0 -22
- package/src/utils/chains/near/relayer/types.js +0 -1
- package/src/utils/chains/near/signAndSend/index.d.ts +0 -1
- package/src/utils/chains/near/signAndSend/index.js +0 -1
- package/src/utils/chains/near/signAndSend/keypair.d.ts +0 -6
- package/src/utils/chains/near/signAndSend/keypair.js +0 -127
- package/src/utils/chains/near/transactionBuilder.d.ts +0 -26
- package/src/utils/chains/near/transactionBuilder.js +0 -72
- package/src/utils/chains/near/types.d.ts +0 -50
- package/src/utils/chains/near/types.js +0 -1
- package/src/utils/index.d.ts +0 -1
- package/src/utils/index.js +0 -1
- package/vocs.config.d.ts +0 -3
- package/vocs.config.js +0 -71
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { type Account, Contract } from '@near-js/accounts'
|
|
2
|
+
import { KeyPair } from '@near-js/crypto'
|
|
3
|
+
import { actionCreators } from '@near-js/transactions'
|
|
4
|
+
import BN from 'bn.js'
|
|
5
|
+
import { base_decode } from 'near-api-js/lib/utils/serialize'
|
|
6
|
+
|
|
7
|
+
import { utils } from '@chains'
|
|
8
|
+
import { ChainSignatureContract as AbstractChainSignatureContract } from '@chains/ChainSignatureContract'
|
|
9
|
+
import type { SignArgs } from '@chains/ChainSignatureContract'
|
|
10
|
+
import type {
|
|
11
|
+
RSVSignature,
|
|
12
|
+
MPCSignature,
|
|
13
|
+
UncompressedPubKeySEC1,
|
|
14
|
+
} from '@chains/types'
|
|
15
|
+
import { chains } from '@utils'
|
|
16
|
+
import { getNearAccount } from '@utils/chains/near/account'
|
|
17
|
+
import {
|
|
18
|
+
DONT_CARE_ACCOUNT_ID,
|
|
19
|
+
NEAR_MAX_GAS,
|
|
20
|
+
} from '@utils/chains/near/constants'
|
|
21
|
+
import { parseSignedDelegateForRelayer } from '@utils/chains/near/relayer'
|
|
22
|
+
import {
|
|
23
|
+
type NearNetworkIds,
|
|
24
|
+
type ChainSignatureContractIds,
|
|
25
|
+
} from '@utils/chains/near/types'
|
|
26
|
+
|
|
27
|
+
const najToUncompressedPubKey = (najPubKey: string): UncompressedPubKeySEC1 => {
|
|
28
|
+
return `04${Buffer.from(base_decode(najPubKey.split(':')[1])).toString('hex')}`
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const requireAccount = (accountId: string): void => {
|
|
32
|
+
if (accountId === DONT_CARE_ACCOUNT_ID) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
'A valid account ID and keypair are required for change methods. Please instantiate a new contract with valid credentials.'
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type NearContract = Contract & {
|
|
40
|
+
public_key: () => Promise<string>
|
|
41
|
+
sign: (args: {
|
|
42
|
+
args: { request: SignArgs }
|
|
43
|
+
gas: BN
|
|
44
|
+
amount: BN
|
|
45
|
+
}) => Promise<MPCSignature>
|
|
46
|
+
experimental_signature_deposit: () => Promise<number>
|
|
47
|
+
derived_public_key: (args: {
|
|
48
|
+
path: string
|
|
49
|
+
predecessor: string
|
|
50
|
+
}) => Promise<string>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface ChainSignatureContractArgs {
|
|
54
|
+
networkId: NearNetworkIds
|
|
55
|
+
contractId: ChainSignatureContractIds
|
|
56
|
+
accountId?: string
|
|
57
|
+
keypair?: KeyPair
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* This contract will default to view methods only.
|
|
62
|
+
* If you want to use the change methods, you need to provide an account and keypair.
|
|
63
|
+
*/
|
|
64
|
+
export class ChainSignatureContract extends AbstractChainSignatureContract {
|
|
65
|
+
private readonly networkId: NearNetworkIds
|
|
66
|
+
private readonly contractId: ChainSignatureContractIds
|
|
67
|
+
private readonly accountId: string
|
|
68
|
+
private readonly keypair: KeyPair
|
|
69
|
+
|
|
70
|
+
constructor({
|
|
71
|
+
networkId,
|
|
72
|
+
contractId,
|
|
73
|
+
accountId = DONT_CARE_ACCOUNT_ID,
|
|
74
|
+
keypair = KeyPair.fromRandom('ed25519'),
|
|
75
|
+
}: ChainSignatureContractArgs) {
|
|
76
|
+
super()
|
|
77
|
+
|
|
78
|
+
this.networkId = networkId
|
|
79
|
+
this.contractId = contractId
|
|
80
|
+
this.accountId = accountId
|
|
81
|
+
this.keypair = keypair
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private async getContract(): Promise<NearContract> {
|
|
85
|
+
const account = await getNearAccount({
|
|
86
|
+
networkId: this.networkId,
|
|
87
|
+
accountId: this.accountId,
|
|
88
|
+
keypair: this.keypair,
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
return new Contract(account, this.contractId, {
|
|
92
|
+
viewMethods: [
|
|
93
|
+
'public_key',
|
|
94
|
+
'experimental_signature_deposit',
|
|
95
|
+
'derived_public_key',
|
|
96
|
+
],
|
|
97
|
+
changeMethods: ['sign'],
|
|
98
|
+
useLocalViewExecution: false,
|
|
99
|
+
}) as unknown as NearContract
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async getCurrentSignatureDeposit(): Promise<BN> {
|
|
103
|
+
const contract = await this.getContract()
|
|
104
|
+
return new BN(
|
|
105
|
+
(await contract.experimental_signature_deposit()).toLocaleString(
|
|
106
|
+
'fullwide',
|
|
107
|
+
{
|
|
108
|
+
useGrouping: false,
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async getDerivedPublicKey(args: {
|
|
115
|
+
path: string
|
|
116
|
+
predecessor: string
|
|
117
|
+
}): Promise<UncompressedPubKeySEC1> {
|
|
118
|
+
const contract = await this.getContract()
|
|
119
|
+
|
|
120
|
+
const najPubKey = await contract.derived_public_key(args)
|
|
121
|
+
return najToUncompressedPubKey(najPubKey)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async sign(args: SignArgs): Promise<RSVSignature> {
|
|
125
|
+
requireAccount(this.accountId)
|
|
126
|
+
|
|
127
|
+
const contract = await this.getContract()
|
|
128
|
+
const deposit = await this.getCurrentSignatureDeposit()
|
|
129
|
+
|
|
130
|
+
const signature = await contract.sign({
|
|
131
|
+
args: { request: args },
|
|
132
|
+
gas: NEAR_MAX_GAS,
|
|
133
|
+
amount: deposit,
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
return utils.toRSV(signature)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
static async signWithRelayer({
|
|
140
|
+
account,
|
|
141
|
+
contract,
|
|
142
|
+
signArgs,
|
|
143
|
+
deposit,
|
|
144
|
+
relayerUrl,
|
|
145
|
+
}: {
|
|
146
|
+
account: Account
|
|
147
|
+
contract: ChainSignatureContractIds
|
|
148
|
+
signArgs: SignArgs
|
|
149
|
+
deposit: BN
|
|
150
|
+
relayerUrl: string
|
|
151
|
+
}): Promise<RSVSignature> {
|
|
152
|
+
const functionCall = actionCreators.functionCall(
|
|
153
|
+
'sign',
|
|
154
|
+
{ request: signArgs },
|
|
155
|
+
BigInt(NEAR_MAX_GAS.toString()),
|
|
156
|
+
BigInt(deposit.toString())
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
const signedDelegate = await account.signedDelegate({
|
|
160
|
+
receiverId: contract,
|
|
161
|
+
actions: [functionCall],
|
|
162
|
+
blockHeightTtl: 60,
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
// Remove the cached access key to prevent nonce reuse
|
|
166
|
+
delete account.accessKeyByPublicKeyCache[
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
168
|
+
signedDelegate.delegateAction.publicKey.toString()
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
const res = await fetch(`${relayerUrl}/send_meta_tx_async`, {
|
|
172
|
+
method: 'POST',
|
|
173
|
+
mode: 'cors',
|
|
174
|
+
body: JSON.stringify(parseSignedDelegateForRelayer(signedDelegate)),
|
|
175
|
+
headers: new Headers({ 'Content-Type': 'application/json' }),
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
const txHash = await res.text()
|
|
179
|
+
const txStatus = await account.connection.provider.txStatus(
|
|
180
|
+
txHash,
|
|
181
|
+
account.accountId,
|
|
182
|
+
'FINAL'
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
const signature = chains.near.transactionBuilder.responseToMpcSignature({
|
|
186
|
+
response: txStatus,
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
if (!signature) {
|
|
190
|
+
throw new Error('Signature error, please retry')
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return signature
|
|
194
|
+
}
|
|
195
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Account, Connection } from '@near-js/accounts'
|
|
2
|
+
import { KeyPair } from '@near-js/crypto'
|
|
3
|
+
import { InMemoryKeyStore } from '@near-js/keystores'
|
|
4
|
+
|
|
5
|
+
import { DONT_CARE_ACCOUNT_ID } from '@utils/chains/near/constants'
|
|
6
|
+
|
|
7
|
+
type SetConnectionArgs =
|
|
8
|
+
| {
|
|
9
|
+
networkId: string
|
|
10
|
+
accountId: string
|
|
11
|
+
keypair: KeyPair
|
|
12
|
+
}
|
|
13
|
+
| {
|
|
14
|
+
networkId: string
|
|
15
|
+
accountId?: never
|
|
16
|
+
keypair?: never
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const getNearAccount = async ({
|
|
20
|
+
networkId,
|
|
21
|
+
accountId = DONT_CARE_ACCOUNT_ID,
|
|
22
|
+
keypair = KeyPair.fromRandom('ed25519'),
|
|
23
|
+
}: SetConnectionArgs): Promise<Account> => {
|
|
24
|
+
const keyStore = new InMemoryKeyStore()
|
|
25
|
+
await keyStore.setKey(networkId, accountId, keypair)
|
|
26
|
+
|
|
27
|
+
const connection = Connection.fromConfig({
|
|
28
|
+
networkId,
|
|
29
|
+
provider: {
|
|
30
|
+
type: 'JsonRpcProvider',
|
|
31
|
+
args: {
|
|
32
|
+
url: {
|
|
33
|
+
testnet: 'https://rpc.testnet.near.org',
|
|
34
|
+
mainnet: 'https://rpc.mainnet.near.org',
|
|
35
|
+
}[networkId],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
signer: { type: 'InMemorySigner', keyStore },
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
return new Account(connection, accountId)
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './relayer'
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type SignedDelegate } from '@near-js/transactions'
|
|
2
|
+
import bs58 from 'bs58'
|
|
3
|
+
|
|
4
|
+
import { type SignedDelegateRelayerFormat } from './types'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Parses the signedDelegate object from the Multi-Party Computation (MPC) format to the Relayer format.
|
|
8
|
+
* @param signedDelegate - The signedDelegate object in MPC format.
|
|
9
|
+
* @returns The signedDelegate object in Relayer format.
|
|
10
|
+
*/
|
|
11
|
+
export function parseSignedDelegateForRelayer(
|
|
12
|
+
signedDelegate: SignedDelegate
|
|
13
|
+
): SignedDelegateRelayerFormat {
|
|
14
|
+
return {
|
|
15
|
+
delegate_action: {
|
|
16
|
+
actions: signedDelegate.delegateAction.actions
|
|
17
|
+
.map((action) => {
|
|
18
|
+
if (action.functionCall) {
|
|
19
|
+
return {
|
|
20
|
+
FunctionCall: {
|
|
21
|
+
method_name: action.functionCall.methodName,
|
|
22
|
+
args: Buffer.from(action.functionCall.args).toString('base64'),
|
|
23
|
+
gas: Number(action.functionCall.gas),
|
|
24
|
+
deposit: action.functionCall.deposit.toString(),
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return undefined
|
|
29
|
+
})
|
|
30
|
+
.flatMap((t) => (t ? [t] : [])),
|
|
31
|
+
nonce: Number(signedDelegate.delegateAction.nonce),
|
|
32
|
+
max_block_height: Number(signedDelegate.delegateAction.maxBlockHeight),
|
|
33
|
+
public_key: signedDelegate.delegateAction.publicKey.toString(),
|
|
34
|
+
receiver_id: signedDelegate.delegateAction.receiverId,
|
|
35
|
+
sender_id: signedDelegate.delegateAction.senderId,
|
|
36
|
+
},
|
|
37
|
+
signature: `ed25519:${bs58.encode(signedDelegate.signature.data)}`,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
interface FunctionCallRelayer {
|
|
2
|
+
FunctionCall: {
|
|
3
|
+
method_name: string
|
|
4
|
+
args: string
|
|
5
|
+
gas: number
|
|
6
|
+
deposit: string
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type ActionsRelayer = FunctionCallRelayer
|
|
11
|
+
|
|
12
|
+
interface DelegateActionRelayerFormat {
|
|
13
|
+
actions: ActionsRelayer[]
|
|
14
|
+
nonce: number
|
|
15
|
+
max_block_height: number
|
|
16
|
+
public_key: string
|
|
17
|
+
receiver_id: string
|
|
18
|
+
sender_id: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface SignedDelegateRelayerFormat {
|
|
22
|
+
delegate_action: DelegateActionRelayerFormat
|
|
23
|
+
signature: string
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as keypair from './keypair'
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { type KeyPair } from '@near-js/crypto'
|
|
2
|
+
|
|
3
|
+
import { Bitcoin, Cosmos, EVM } from '@chains'
|
|
4
|
+
import { BTCRpcAdapters } from '@chains/Bitcoin/BTCRpcAdapter'
|
|
5
|
+
import { type Response } from '@chains/types'
|
|
6
|
+
import { getNearAccount } from '@utils/chains/near/account'
|
|
7
|
+
import { ChainSignatureContract } from '@utils/chains/near/ChainSignatureContract'
|
|
8
|
+
import {
|
|
9
|
+
type BitcoinRequest,
|
|
10
|
+
type CosmosRequest,
|
|
11
|
+
type EVMRequest,
|
|
12
|
+
} from '@utils/chains/near/types'
|
|
13
|
+
|
|
14
|
+
export const EVMTransaction = async (
|
|
15
|
+
req: EVMRequest,
|
|
16
|
+
keyPair: KeyPair
|
|
17
|
+
): Promise<Response> => {
|
|
18
|
+
try {
|
|
19
|
+
const account = await getNearAccount({
|
|
20
|
+
networkId: req.nearAuthentication.networkId,
|
|
21
|
+
accountId: req.nearAuthentication.accountId,
|
|
22
|
+
keypair: keyPair,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const contract = new ChainSignatureContract({
|
|
26
|
+
networkId: req.nearAuthentication.networkId,
|
|
27
|
+
contractId: req.chainConfig.contract,
|
|
28
|
+
accountId: account.accountId,
|
|
29
|
+
keypair: keyPair,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const evm = new EVM({
|
|
33
|
+
rpcUrl: req.chainConfig.providerUrl,
|
|
34
|
+
contract,
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const { transaction, mpcPayloads } = await evm.getMPCPayloadAndTransaction(
|
|
38
|
+
req.transaction
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
const signature = await contract.sign({
|
|
42
|
+
payload: mpcPayloads[0].payload,
|
|
43
|
+
path: req.derivationPath,
|
|
44
|
+
key_version: 0,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const txSerialized = evm.addSignature({
|
|
48
|
+
transaction,
|
|
49
|
+
mpcSignatures: [signature],
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const txHash = await evm.broadcastTx(txSerialized)
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
transactionHash: txHash,
|
|
56
|
+
success: true,
|
|
57
|
+
}
|
|
58
|
+
} catch (e: unknown) {
|
|
59
|
+
console.error(e)
|
|
60
|
+
return {
|
|
61
|
+
success: false,
|
|
62
|
+
errorMessage: e instanceof Error ? e.message : String(e),
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const BTCTransaction = async (
|
|
68
|
+
req: BitcoinRequest,
|
|
69
|
+
keyPair: KeyPair
|
|
70
|
+
): Promise<Response> => {
|
|
71
|
+
try {
|
|
72
|
+
const account = await getNearAccount({
|
|
73
|
+
networkId: req.nearAuthentication.networkId,
|
|
74
|
+
accountId: req.nearAuthentication.accountId,
|
|
75
|
+
keypair: keyPair,
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const contract = new ChainSignatureContract({
|
|
79
|
+
networkId: req.nearAuthentication.networkId,
|
|
80
|
+
contractId: req.chainConfig.contract,
|
|
81
|
+
accountId: account.accountId,
|
|
82
|
+
keypair: keyPair,
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
const btc = new Bitcoin({
|
|
86
|
+
btcRpcAdapter: new BTCRpcAdapters.Mempool(req.chainConfig.providerUrl),
|
|
87
|
+
contract,
|
|
88
|
+
network: req.chainConfig.network,
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
const { transaction, mpcPayloads } = await btc.getMPCPayloadAndTransaction(
|
|
92
|
+
req.transaction
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
const signatures = await Promise.all(
|
|
96
|
+
mpcPayloads.map(
|
|
97
|
+
async ({ payload }) =>
|
|
98
|
+
await contract.sign({
|
|
99
|
+
payload,
|
|
100
|
+
path: req.derivationPath,
|
|
101
|
+
key_version: 0,
|
|
102
|
+
})
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
const txSerialized = btc.addSignature({
|
|
107
|
+
transaction,
|
|
108
|
+
mpcSignatures: signatures,
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
const txHash = await btc.broadcastTx(txSerialized)
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
transactionHash: txHash,
|
|
115
|
+
success: true,
|
|
116
|
+
}
|
|
117
|
+
} catch (e: unknown) {
|
|
118
|
+
return {
|
|
119
|
+
success: false,
|
|
120
|
+
errorMessage: e instanceof Error ? e.message : String(e),
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const CosmosTransaction = async (
|
|
126
|
+
req: CosmosRequest,
|
|
127
|
+
keyPair: KeyPair
|
|
128
|
+
): Promise<Response> => {
|
|
129
|
+
try {
|
|
130
|
+
const account = await getNearAccount({
|
|
131
|
+
networkId: req.nearAuthentication.networkId,
|
|
132
|
+
accountId: req.nearAuthentication.accountId,
|
|
133
|
+
keypair: keyPair,
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
const contract = new ChainSignatureContract({
|
|
137
|
+
networkId: req.nearAuthentication.networkId,
|
|
138
|
+
contractId: req.chainConfig.contract,
|
|
139
|
+
accountId: account.accountId,
|
|
140
|
+
keypair: keyPair,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const cosmos = new Cosmos({
|
|
144
|
+
contract,
|
|
145
|
+
chainId: req.chainConfig.chainId,
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
const { transaction, mpcPayloads } =
|
|
149
|
+
await cosmos.getMPCPayloadAndTransaction(req.transaction)
|
|
150
|
+
|
|
151
|
+
const signatures = await Promise.all(
|
|
152
|
+
mpcPayloads.map(
|
|
153
|
+
async ({ payload }) =>
|
|
154
|
+
await contract.sign({
|
|
155
|
+
payload,
|
|
156
|
+
path: req.derivationPath,
|
|
157
|
+
key_version: 0,
|
|
158
|
+
})
|
|
159
|
+
)
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
const txSerialized = cosmos.addSignature({
|
|
163
|
+
transaction,
|
|
164
|
+
mpcSignatures: signatures,
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
const txHash = await cosmos.broadcastTx(txSerialized)
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
transactionHash: txHash,
|
|
171
|
+
success: true,
|
|
172
|
+
}
|
|
173
|
+
} catch (e: unknown) {
|
|
174
|
+
console.error(e)
|
|
175
|
+
return {
|
|
176
|
+
success: false,
|
|
177
|
+
errorMessage: e instanceof Error ? e.message : String(e),
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Action,
|
|
3
|
+
FinalExecutionOutcome,
|
|
4
|
+
NetworkId,
|
|
5
|
+
} from '@near-wallet-selector/core'
|
|
6
|
+
import BN from 'bn.js'
|
|
7
|
+
import { type ExecutionOutcomeWithId } from 'near-api-js/lib/providers'
|
|
8
|
+
|
|
9
|
+
import { utils } from '@chains'
|
|
10
|
+
import {
|
|
11
|
+
type RSVSignature,
|
|
12
|
+
type KeyDerivationPath,
|
|
13
|
+
type MPCSignature,
|
|
14
|
+
type MPCPayloads,
|
|
15
|
+
} from '@chains/types'
|
|
16
|
+
import { ChainSignatureContract } from '@utils/chains/near/ChainSignatureContract'
|
|
17
|
+
import { NEAR_MAX_GAS } from '@utils/chains/near/constants'
|
|
18
|
+
import {
|
|
19
|
+
type NFTKeysContracts,
|
|
20
|
+
type ChainSignatureContractIds,
|
|
21
|
+
} from '@utils/chains/near/types'
|
|
22
|
+
|
|
23
|
+
export const mpcPayloadsToChainSigTransaction = async ({
|
|
24
|
+
networkId,
|
|
25
|
+
contractId,
|
|
26
|
+
mpcPayloads,
|
|
27
|
+
path,
|
|
28
|
+
}: {
|
|
29
|
+
networkId: NetworkId
|
|
30
|
+
contractId: ChainSignatureContractIds
|
|
31
|
+
mpcPayloads: MPCPayloads
|
|
32
|
+
path: KeyDerivationPath
|
|
33
|
+
}): Promise<{
|
|
34
|
+
receiverId: string
|
|
35
|
+
actions: Action[]
|
|
36
|
+
}> => {
|
|
37
|
+
const contract = new ChainSignatureContract({
|
|
38
|
+
networkId,
|
|
39
|
+
contractId,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const currentContractFee = await contract.getCurrentSignatureDeposit()
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
receiverId: contractId,
|
|
46
|
+
actions: mpcPayloads.map(({ payload }) => ({
|
|
47
|
+
type: 'FunctionCall',
|
|
48
|
+
params: {
|
|
49
|
+
methodName: 'sign',
|
|
50
|
+
args: {
|
|
51
|
+
request: {
|
|
52
|
+
payload: Array.from(payload),
|
|
53
|
+
path,
|
|
54
|
+
key_version: 0,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
gas: NEAR_MAX_GAS.div(new BN(mpcPayloads.length)).toString(),
|
|
58
|
+
deposit: currentContractFee?.toString() || '1',
|
|
59
|
+
},
|
|
60
|
+
})),
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const mpcPayloadsToNFTKeysTransaction = async ({
|
|
65
|
+
networkId,
|
|
66
|
+
chainSigContract,
|
|
67
|
+
nftKeysContract,
|
|
68
|
+
mpcPayloads,
|
|
69
|
+
path,
|
|
70
|
+
tokenId,
|
|
71
|
+
}: {
|
|
72
|
+
networkId: NetworkId
|
|
73
|
+
chainSigContract: ChainSignatureContractIds
|
|
74
|
+
nftKeysContract: NFTKeysContracts
|
|
75
|
+
mpcPayloads: MPCPayloads
|
|
76
|
+
path: KeyDerivationPath
|
|
77
|
+
tokenId: string
|
|
78
|
+
}): Promise<{
|
|
79
|
+
receiverId: string
|
|
80
|
+
actions: Action[]
|
|
81
|
+
}> => {
|
|
82
|
+
const contract = new ChainSignatureContract({
|
|
83
|
+
networkId,
|
|
84
|
+
contractId: chainSigContract,
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
const currentContractFee = await contract.getCurrentSignatureDeposit()
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
receiverId: nftKeysContract,
|
|
91
|
+
actions: mpcPayloads.map(({ payload }) => ({
|
|
92
|
+
type: 'FunctionCall',
|
|
93
|
+
params: {
|
|
94
|
+
methodName: 'ckt_sign_hash',
|
|
95
|
+
args: {
|
|
96
|
+
token_id: tokenId,
|
|
97
|
+
path,
|
|
98
|
+
payload: Array.from(payload),
|
|
99
|
+
},
|
|
100
|
+
gas: NEAR_MAX_GAS.div(new BN(mpcPayloads.length)).toString(),
|
|
101
|
+
deposit: currentContractFee?.toString() || '1',
|
|
102
|
+
},
|
|
103
|
+
})),
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const responseToMpcSignature = ({
|
|
108
|
+
response,
|
|
109
|
+
}: {
|
|
110
|
+
response: FinalExecutionOutcome
|
|
111
|
+
}): RSVSignature | undefined => {
|
|
112
|
+
const signature: string = response.receipts_outcome.reduce<string>(
|
|
113
|
+
(acc: string, curr: ExecutionOutcomeWithId) => {
|
|
114
|
+
if (acc) {
|
|
115
|
+
return acc
|
|
116
|
+
}
|
|
117
|
+
const { status } = curr.outcome
|
|
118
|
+
return (
|
|
119
|
+
(typeof status === 'object' &&
|
|
120
|
+
status.SuccessValue &&
|
|
121
|
+
status.SuccessValue !== '' &&
|
|
122
|
+
Buffer.from(status.SuccessValue, 'base64').toString('utf-8')) ||
|
|
123
|
+
''
|
|
124
|
+
)
|
|
125
|
+
},
|
|
126
|
+
''
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
if (signature) {
|
|
130
|
+
const parsedJSONSignature = JSON.parse(signature) as {
|
|
131
|
+
Ok: MPCSignature
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return utils.toRSV(parsedJSONSignature.Ok)
|
|
135
|
+
} else {
|
|
136
|
+
return undefined
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BTCTransactionRequest,
|
|
3
|
+
BTCNetworkIds,
|
|
4
|
+
} from '@chains/Bitcoin/types'
|
|
5
|
+
import type {
|
|
6
|
+
CosmosNetworkIds,
|
|
7
|
+
CosmosTransactionRequest,
|
|
8
|
+
} from '@chains/Cosmos/types'
|
|
9
|
+
import { type EVMTransactionRequest } from '@chains/EVM/types'
|
|
10
|
+
import type { KeyDerivationPath } from '@chains/types'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
Available ChainSignature contracts:
|
|
14
|
+
- Mainnet: v1.signer
|
|
15
|
+
- Testnet: v1.signer-prod.testnet
|
|
16
|
+
- Development (unstable): v1.signer-dev.testnet
|
|
17
|
+
*/
|
|
18
|
+
export type ChainSignatureContractIds = string
|
|
19
|
+
|
|
20
|
+
export type NFTKeysContracts = string
|
|
21
|
+
|
|
22
|
+
export type NearNetworkIds = 'mainnet' | 'testnet'
|
|
23
|
+
|
|
24
|
+
export interface ChainProvider {
|
|
25
|
+
providerUrl: string
|
|
26
|
+
contract: ChainSignatureContractIds
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface NearAuthentication {
|
|
30
|
+
networkId: NearNetworkIds
|
|
31
|
+
accountId: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type EVMChainConfigWithProviders = ChainProvider
|
|
35
|
+
|
|
36
|
+
export interface EVMRequest {
|
|
37
|
+
transaction: EVMTransactionRequest
|
|
38
|
+
chainConfig: EVMChainConfigWithProviders
|
|
39
|
+
nearAuthentication: NearAuthentication
|
|
40
|
+
fastAuthRelayerUrl?: string
|
|
41
|
+
derivationPath: KeyDerivationPath
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type BTCChainConfigWithProviders = ChainProvider & {
|
|
45
|
+
network: BTCNetworkIds
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface BitcoinRequest {
|
|
49
|
+
transaction: BTCTransactionRequest
|
|
50
|
+
chainConfig: BTCChainConfigWithProviders
|
|
51
|
+
nearAuthentication: NearAuthentication
|
|
52
|
+
fastAuthRelayerUrl?: string
|
|
53
|
+
derivationPath: KeyDerivationPath
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface CosmosChainConfig {
|
|
57
|
+
contract: ChainSignatureContractIds
|
|
58
|
+
chainId: CosmosNetworkIds
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface CosmosRequest {
|
|
62
|
+
chainConfig: CosmosChainConfig
|
|
63
|
+
transaction: CosmosTransactionRequest
|
|
64
|
+
nearAuthentication: NearAuthentication
|
|
65
|
+
derivationPath: KeyDerivationPath
|
|
66
|
+
fastAuthRelayerUrl?: string
|
|
67
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as chains from './chains'
|