@alephium/web3 1.11.5 → 1.12.0-beta.0

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.
Files changed (37) hide show
  1. package/dist/alephium-web3.min.js +1 -1
  2. package/dist/alephium-web3.min.js.map +1 -1
  3. package/dist/src/address/address.d.ts +11 -1
  4. package/dist/src/address/address.js +117 -11
  5. package/dist/src/api/api-alephium.d.ts +101 -4
  6. package/dist/src/api/api-alephium.js +51 -1
  7. package/dist/src/api/node-provider.d.ts +2 -0
  8. package/dist/src/api/node-provider.js +1 -0
  9. package/dist/src/api/types.d.ts +1 -1
  10. package/dist/src/api/types.js +10 -5
  11. package/dist/src/codec/lockup-script-codec.d.ts +11 -2
  12. package/dist/src/codec/lockup-script-codec.js +8 -1
  13. package/dist/src/codec/unlock-script-codec.d.ts +11 -3
  14. package/dist/src/codec/unlock-script-codec.js +14 -4
  15. package/dist/src/contract/contract.d.ts +3 -3
  16. package/dist/src/contract/contract.js +12 -5
  17. package/dist/src/contract/ralph.js +2 -1
  18. package/dist/src/signer/signer.js +1 -1
  19. package/dist/src/signer/tx-builder.d.ts +7 -1
  20. package/dist/src/signer/tx-builder.js +67 -0
  21. package/dist/src/signer/types.d.ts +29 -2
  22. package/dist/src/signer/types.js +3 -0
  23. package/dist/src/utils/sign.js +2 -2
  24. package/dist/src/utils/webcrypto.d.ts +3 -1
  25. package/package.json +3 -3
  26. package/src/address/address.ts +120 -12
  27. package/src/api/api-alephium.ts +474 -144
  28. package/src/api/node-provider.ts +3 -0
  29. package/src/api/types.ts +10 -5
  30. package/src/codec/lockup-script-codec.ts +19 -2
  31. package/src/codec/unlock-script-codec.ts +23 -8
  32. package/src/contract/contract.ts +33 -10
  33. package/src/contract/ralph.ts +5 -2
  34. package/src/signer/signer.ts +1 -1
  35. package/src/signer/tx-builder.ts +88 -1
  36. package/src/signer/types.ts +36 -2
  37. package/src/utils/sign.ts +2 -2
@@ -55,6 +55,7 @@ interface NodeProviderApis {
55
55
  utils: NodeApi<string>['utils']
56
56
  miners: NodeApi<string>['miners']
57
57
  events: NodeApi<string>['events']
58
+ groupless: NodeApi<string>['groupless']
58
59
  }
59
60
 
60
61
  export class NodeProvider implements NodeProviderApis {
@@ -69,6 +70,7 @@ export class NodeProvider implements NodeProviderApis {
69
70
  readonly utils: NodeApi<string>['utils']
70
71
  readonly miners: NodeApi<string>['miners']
71
72
  readonly events: NodeApi<string>['events']
73
+ readonly groupless: NodeApi<string>['groupless']
72
74
 
73
75
  constructor(baseUrl: string, apiKey?: string, customFetch?: typeof fetch)
74
76
  constructor(provider: NodeProvider)
@@ -95,6 +97,7 @@ export class NodeProvider implements NodeProviderApis {
95
97
  this.utils = { ...nodeApi.utils }
96
98
  this.miners = { ...nodeApi.miners }
97
99
  this.events = { ...nodeApi.events }
100
+ this.groupless = { ...nodeApi.groupless }
98
101
  requestWithLog(this)
99
102
  }
100
103
 
package/src/api/types.ts CHANGED
@@ -16,6 +16,7 @@ You should have received a copy of the GNU Lesser General Public License
16
16
  along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
 
19
+ import { hasExplicitGroupIndex } from '../address'
19
20
  import { ZERO_ADDRESS } from '../constants'
20
21
  import { isDebugModeEnabled } from '../debug'
21
22
  import { TraceableError } from '../error'
@@ -99,14 +100,18 @@ export function toApiByteVec(v: Val): string {
99
100
  throw new Error(`Invalid hex-string: ${v}`)
100
101
  }
101
102
 
102
- export function toApiAddress(v: Val): string {
103
- if (typeof v === 'string') {
103
+ export function toApiAddress(v0: Val): string {
104
+ if (typeof v0 === 'string') {
105
+ let v = v0
106
+ if (hasExplicitGroupIndex(v)) {
107
+ v = v.slice(0, -2)
108
+ }
104
109
  if (isBase58(v)) {
105
- return v
110
+ return v0
106
111
  }
107
- throw new Error(`Invalid base58 string: ${v}`)
112
+ throw new Error(`Invalid base58 string: ${v0}`)
108
113
  } else {
109
- throw new Error(`Invalid value: ${v}, expected a base58 string`)
114
+ throw new Error(`Invalid value: ${v0}, expected a base58 string`)
110
115
  }
111
116
  }
112
117
 
@@ -16,8 +16,9 @@ You should have received a copy of the GNU Lesser General Public License
16
16
  along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
  import { i32Codec } from './compact-int-codec'
19
- import { byte32Codec, EnumCodec, ObjectCodec } from './codec'
19
+ import { byte32Codec, byteCodec, EnumCodec, FixedSizeCodec, ObjectCodec } from './codec'
20
20
  import { ArrayCodec } from './array-codec'
21
+ import { intAs4BytesCodec } from './int-as-4bytes-codec'
21
22
 
22
23
  export type PublicKeyHash = Uint8Array
23
24
  export type P2PKH = Uint8Array
@@ -31,20 +32,36 @@ export interface P2MPKH {
31
32
  m: number
32
33
  }
33
34
 
35
+ export interface P2PC {
36
+ type: number
37
+ publicKey: Uint8Array
38
+ checkSum: Uint8Array
39
+ group: number
40
+ }
41
+
34
42
  const p2mpkhCodec = new ObjectCodec<P2MPKH>({
35
43
  publicKeyHashes: new ArrayCodec(byte32Codec),
36
44
  m: i32Codec
37
45
  })
38
46
 
47
+ const p2pkCodec = new ObjectCodec<P2PC>({
48
+ type: byteCodec,
49
+ publicKey: new FixedSizeCodec(33),
50
+ checkSum: new FixedSizeCodec(4),
51
+ group: byteCodec
52
+ })
53
+
39
54
  export type LockupScript =
40
55
  | { kind: 'P2PKH'; value: P2PKH }
41
56
  | { kind: 'P2MPKH'; value: P2MPKH }
42
57
  | { kind: 'P2SH'; value: P2SH }
43
58
  | { kind: 'P2C'; value: P2C }
59
+ | { kind: 'P2PK'; value: P2PC }
44
60
 
45
61
  export const lockupScriptCodec = new EnumCodec<LockupScript>('lockup script', {
46
62
  P2PKH: byte32Codec,
47
63
  P2MPKH: p2mpkhCodec,
48
64
  P2SH: byte32Codec,
49
- P2C: byte32Codec
65
+ P2C: byte32Codec,
66
+ P2PK: p2pkCodec
50
67
  })
@@ -17,13 +17,13 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
  import { ArrayCodec } from './array-codec'
19
19
  import { i32Codec } from './compact-int-codec'
20
- import { Codec, EnumCodec, FixedSizeCodec, ObjectCodec } from './codec'
20
+ import { byteCodec, Codec, EnumCodec, FixedSizeCodec, ObjectCodec } from './codec'
21
21
  import { Script, scriptCodec } from './script-codec'
22
22
  import { Val, valsCodec } from './val'
23
23
 
24
- export type P2PKH = Uint8Array
24
+ export type PublicKey = Uint8Array
25
25
  export interface KeyWithIndex {
26
- publicKey: P2PKH
26
+ publicKey: PublicKey
27
27
  index: number
28
28
  }
29
29
  export type P2MPKH = KeyWithIndex[]
@@ -32,16 +32,21 @@ export interface P2SH {
32
32
  params: Val[]
33
33
  }
34
34
  export type SameAsPrevious = 'SameAsPrevious'
35
+ export type P2PK = 'P2PK'
36
+
37
+ export type KeyType = number
35
38
 
36
39
  export type UnlockScript =
37
- | { kind: 'P2PKH'; value: P2PKH }
40
+ | { kind: 'P2PKH'; value: PublicKey }
38
41
  | { kind: 'P2MPKH'; value: P2MPKH }
39
42
  | { kind: 'P2SH'; value: P2SH }
40
43
  | { kind: 'SameAsPrevious'; value: SameAsPrevious }
44
+ | { kind: 'PoLW'; value: PublicKey }
45
+ | { kind: 'P2PK'; value: P2PK }
41
46
 
42
- const p2pkhCodec = new FixedSizeCodec(33)
47
+ const publicKeyCodec = new FixedSizeCodec(33)
43
48
  const keyWithIndexCodec = new ObjectCodec<KeyWithIndex>({
44
- publicKey: p2pkhCodec,
49
+ publicKey: publicKeyCodec,
45
50
  index: i32Codec
46
51
  })
47
52
  const p2mpkhCodec: Codec<P2MPKH> = new ArrayCodec(keyWithIndexCodec)
@@ -57,12 +62,22 @@ const sameAsPreviousCodec = new (class extends Codec<SameAsPrevious> {
57
62
  return 'SameAsPrevious'
58
63
  }
59
64
  })()
65
+ const p2pkCodec = new (class extends Codec<P2PK> {
66
+ encode(): Uint8Array {
67
+ return new Uint8Array([])
68
+ }
69
+ _decode(): P2PK {
70
+ return 'P2PK'
71
+ }
72
+ })()
60
73
 
61
74
  export const unlockScriptCodec = new EnumCodec<UnlockScript>('unlock script', {
62
- P2PKH: p2pkhCodec,
75
+ P2PKH: publicKeyCodec,
63
76
  P2MPKH: p2mpkhCodec,
64
77
  P2SH: p2shCodec,
65
- SameAsPrevious: sameAsPreviousCodec
78
+ SameAsPrevious: sameAsPreviousCodec,
79
+ PoLW: publicKeyCodec,
80
+ P2PK: p2pkCodec
66
81
  })
67
82
 
68
83
  export const encodedSameAsPrevious = unlockScriptCodec.encode({ kind: 'SameAsPrevious', value: 'SameAsPrevious' })
@@ -58,7 +58,13 @@ import {
58
58
  isHexString,
59
59
  hexToString
60
60
  } from '../utils'
61
- import { contractIdFromAddress, groupOfAddress, addressFromContractId, subContractId } from '../address'
61
+ import {
62
+ contractIdFromAddress,
63
+ groupOfAddress,
64
+ addressFromContractId,
65
+ subContractId,
66
+ isGrouplessAddressWithoutGroupIndex,
67
+ } from '../address'
62
68
  import { getCurrentNodeProvider } from '../global'
63
69
  import { EventSubscribeOptions, EventSubscription, subscribeToEvents } from './events'
64
70
  import { MINIMAL_CONTRACT_DEPOSIT, ONE_ALPH, TOTAL_NUMBER_OF_GROUPS } from '../constants'
@@ -482,7 +488,7 @@ export class Contract extends Artifact {
482
488
  blockTimeStamp: params.blockTimeStamp,
483
489
  txId: params.txId,
484
490
  address: params.address,
485
- callerAddress: params.callerAddress,
491
+ callerContractAddress: params.callerContractAddress,
486
492
  bytecode: this.isInlineFunc(methodIndex) ? this.getByteCodeForTesting() : this.bytecodeDebug,
487
493
  initialImmFields: immFields,
488
494
  initialMutFields: mutFields,
@@ -590,7 +596,8 @@ export class Contract extends Artifact {
590
596
 
591
597
  async txParamsForDeployment<P extends Fields>(
592
598
  signer: SignerProvider,
593
- params: DeployContractParams<P>
599
+ params: DeployContractParams<P>,
600
+ group?: number
594
601
  ): Promise<SignDeployContractTxParams> {
595
602
  const isDevnet = await this.isDevnet(signer)
596
603
  const initialFields: Fields = params.initialFields ?? {}
@@ -600,8 +607,16 @@ export class Contract extends Artifact {
600
607
  params.exposePrivateFunctions ?? false
601
608
  )
602
609
  const selectedAccount = await signer.getSelectedAccount()
610
+ let signerAddress = selectedAccount.address
611
+ if (isGrouplessAddressWithoutGroupIndex(selectedAccount.address)) {
612
+ if (group === undefined) {
613
+ throw new Error('Groupless address requires explicit group number for contract deployment')
614
+ }
615
+ signerAddress = `${selectedAccount.address}:${group}`
616
+ }
617
+
603
618
  const signerParams: SignDeployContractTxParams = {
604
- signerAddress: selectedAccount.address,
619
+ signerAddress,
605
620
  signerKeyType: selectedAccount.keyType,
606
621
  bytecode: bytecode,
607
622
  initialAttoAlphAmount: params?.initialAttoAlphAmount,
@@ -967,7 +982,7 @@ export interface TestContractParams<
967
982
  > {
968
983
  group?: number // default 0
969
984
  address?: string
970
- callerAddress?: string
985
+ callerContractAddress?: string
971
986
  blockHash?: string
972
987
  blockTimeStamp?: number
973
988
  txId?: string
@@ -1079,11 +1094,19 @@ export abstract class ContractFactory<I extends ContractInstance, F extends Fiel
1079
1094
 
1080
1095
  abstract at(address: string): I
1081
1096
 
1082
- async deploy(signer: SignerProvider, deployParams: DeployContractParams<F>): Promise<DeployContractResult<I>> {
1083
- const signerParams = await this.contract.txParamsForDeployment(signer, {
1084
- ...deployParams,
1085
- initialFields: addStdIdToFields(this.contract, deployParams.initialFields)
1086
- })
1097
+ async deploy(
1098
+ signer: SignerProvider,
1099
+ deployParams: DeployContractParams<F>,
1100
+ group?: number
1101
+ ): Promise<DeployContractResult<I>> {
1102
+ const signerParams = await this.contract.txParamsForDeployment(
1103
+ signer,
1104
+ {
1105
+ ...deployParams,
1106
+ initialFields: addStdIdToFields(this.contract, deployParams.initialFields)
1107
+ },
1108
+ group
1109
+ )
1087
1110
  const result = await signer.signAndSubmitDeployContractTx(signerParams)
1088
1111
  return {
1089
1112
  ...result,
@@ -30,10 +30,13 @@ import {
30
30
  instrCodec,
31
31
  u256Codec,
32
32
  toU256,
33
- toI256
33
+ toI256,
34
+ intAs4BytesCodec
34
35
  } from '../codec'
35
36
  import { boolCodec } from '../codec/codec'
36
37
  import { TraceableError } from '../error'
38
+ import djb2 from '../utils/djb2'
39
+ import { addressToBytes, groupFromHint } from '../address'
37
40
 
38
41
  export function encodeByteVec(hex: string): Uint8Array {
39
42
  if (!isHexString(hex)) {
@@ -45,7 +48,7 @@ export function encodeByteVec(hex: string): Uint8Array {
45
48
  }
46
49
 
47
50
  export function encodeAddress(address: string): Uint8Array {
48
- return bs58.decode(address)
51
+ return addressToBytes(address)
49
52
  }
50
53
 
51
54
  export enum VmValType {
@@ -298,5 +298,5 @@ export function toApiDestinations(data: Destination[]): node.Destination[] {
298
298
  }
299
299
 
300
300
  export function fromApiDestination(data: node.Destination): Destination {
301
- return { ...data, attoAlphAmount: fromApiNumber256(data.attoAlphAmount), tokens: fromApiTokens(data.tokens) }
301
+ return { ...data, attoAlphAmount: fromApiNumber256(data.attoAlphAmount ?? '0'), tokens: fromApiTokens(data.tokens) }
302
302
  }
@@ -34,7 +34,11 @@ import {
34
34
  SignTransferTxParams,
35
35
  SignTransferTxResult,
36
36
  SignUnsignedTxParams,
37
- SignUnsignedTxResult
37
+ SignUnsignedTxResult,
38
+ SignGrouplessTransferTxParams,
39
+ SignGrouplessDeployContractTxParams,
40
+ SignTransferChainedTxResult,
41
+ SignGrouplessExecuteScriptTxParams
38
42
  } from './types'
39
43
  import { unsignedTxCodec } from '../codec'
40
44
  import { groupIndexOfTransaction } from '../transaction'
@@ -154,6 +158,51 @@ export abstract class TransactionBuilder {
154
158
  return results
155
159
  }
156
160
 
161
+ async buildGrouplessTransferTx(
162
+ params: SignGrouplessTransferTxParams
163
+ ): Promise<Omit<SignChainedTxResult, 'signature'>[]> {
164
+ const data = this.buildGrouplessTransferTxParams(params)
165
+ const response = await this.nodeProvider.groupless.postGrouplessTransfer(data)
166
+ return response.map((result) => {
167
+ return {
168
+ ...this.convertTransferTxResult(result),
169
+ type: 'Transfer' as const
170
+ }
171
+ })
172
+ }
173
+
174
+ async buildGrouplessDeployContractTx(
175
+ params: SignGrouplessDeployContractTxParams
176
+ ): Promise<Omit<SignChainedTxResult, 'signature'>[]> {
177
+ const data = this.buildGrouplessDeployContractTxParams(params)
178
+ const response = await this.nodeProvider.groupless.postGrouplessDeployContract(data)
179
+ const transferTxs = response.transferTxs.map((result) => ({
180
+ ...this.convertTransferTxResult(result),
181
+ type: 'Transfer' as const
182
+ }))
183
+ const deployContractTx = {
184
+ ...this.convertDeployContractTxResult(response.deployContractTx),
185
+ type: 'DeployContract' as const
186
+ }
187
+ return [...transferTxs, deployContractTx]
188
+ }
189
+
190
+ async buildGrouplessExecuteScriptTx(
191
+ params: SignGrouplessExecuteScriptTxParams
192
+ ): Promise<Omit<SignChainedTxResult, 'signature'>[]> {
193
+ const data = this.buildGrouplessExecuteScriptTxParams(params)
194
+ const response = await this.nodeProvider.groupless.postGrouplessExecuteScript(data)
195
+ const transferTxs = response.transferTxs.map((result) => ({
196
+ ...this.convertTransferTxResult(result),
197
+ type: 'Transfer' as const
198
+ }))
199
+ const executeScriptTx = {
200
+ ...this.convertExecuteScriptTxResult(response.executeScriptTx),
201
+ type: 'ExecuteScript' as const
202
+ }
203
+ return [...transferTxs, executeScriptTx]
204
+ }
205
+
157
206
  static buildUnsignedTx(params: SignUnsignedTxParams): Omit<SignUnsignedTxResult, 'signature'> {
158
207
  const unsignedTxBin = hexToBinUnsafe(params.unsignedTx)
159
208
  const decoded = unsignedTxCodec.decode(unsignedTxBin)
@@ -182,6 +231,44 @@ export abstract class TransactionBuilder {
182
231
  }
183
232
  }
184
233
 
234
+ private buildGrouplessTransferTxParams(params: SignGrouplessTransferTxParams): node.BuildGrouplessTransferTx {
235
+ return {
236
+ fromAddress: params.fromAddress,
237
+ destinations: toApiDestinations(params.destinations),
238
+ gasPrice: toApiNumber256Optional(params.gasPrice),
239
+ targetBlockHash: params.targetBlockHash
240
+ }
241
+ }
242
+
243
+ private buildGrouplessDeployContractTxParams(
244
+ params: SignGrouplessDeployContractTxParams
245
+ ): node.BuildGrouplessDeployContractTx {
246
+ return {
247
+ fromAddress: params.fromAddress,
248
+ bytecode: params.bytecode,
249
+ initialAttoAlphAmount: toApiNumber256Optional(params.initialAttoAlphAmount),
250
+ initialTokenAmounts: toApiTokens(params.initialTokenAmounts),
251
+ issueTokenAmount: toApiNumber256Optional(params.issueTokenAmount),
252
+ issueTokenTo: params.issueTokenTo,
253
+ gasPrice: toApiNumber256Optional(params.gasPrice),
254
+ targetBlockHash: params.targetBlockHash
255
+ }
256
+ }
257
+
258
+ private buildGrouplessExecuteScriptTxParams(
259
+ params: SignGrouplessExecuteScriptTxParams
260
+ ): node.BuildGrouplessExecuteScriptTx {
261
+ return {
262
+ fromAddress: params.fromAddress,
263
+ bytecode: params.bytecode,
264
+ attoAlphAmount: toApiNumber256Optional(params.attoAlphAmount),
265
+ tokens: toApiTokens(params.tokens),
266
+ gasPrice: toApiNumber256Optional(params.gasPrice),
267
+ targetBlockHash: params.targetBlockHash,
268
+ gasEstimationMultiplier: params.gasEstimationMultiplier
269
+ }
270
+ }
271
+
185
272
  private buildDeployContractTxParams(
186
273
  params: SignDeployContractTxParams,
187
274
  publicKey: string
@@ -18,6 +18,7 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
18
18
 
19
19
  import { Number256, Token } from '../api'
20
20
  import { node } from '../api'
21
+ import { SimulationResult } from '../api/api-alephium'
21
22
  import { Eq, assertType, NetworkId } from '../utils'
22
23
 
23
24
  export type Address = string
@@ -33,7 +34,7 @@ export interface Destination {
33
34
  }
34
35
  assertType<Eq<keyof Destination, keyof node.Destination>>
35
36
 
36
- export type KeyType = 'default' | 'bip340-schnorr'
37
+ export type KeyType = 'default' | 'bip340-schnorr' | 'groupless'
37
38
 
38
39
  export interface Account {
39
40
  keyType: KeyType
@@ -113,7 +114,7 @@ export interface SignExecuteScriptTxResult {
113
114
  signature: string
114
115
  gasAmount: number
115
116
  gasPrice: Number256
116
- simulatedOutputs: node.Output[]
117
+ simulationResult: SimulationResult
117
118
  }
118
119
  assertType<
119
120
  Eq<
@@ -159,6 +160,39 @@ export type SignChainedTxResult =
159
160
  | SignDeployContractChainedTxResult
160
161
  | SignExecuteScriptChainedTxResult
161
162
 
163
+ export interface SignGrouplessTransferTxParams {
164
+ fromAddress: string
165
+ destinations: Destination[]
166
+ gasPrice?: Number256
167
+ targetBlockHash?: string
168
+ }
169
+ assertType<Eq<keyof SignGrouplessTransferTxParams, keyof node.BuildGrouplessTransferTx>>()
170
+ export interface SignGrouplessDeployContractTxParams {
171
+ fromAddress: string
172
+ bytecode: string
173
+ initialAttoAlphAmount?: Number256
174
+ initialTokenAmounts?: Token[]
175
+ issueTokenAmount?: Number256
176
+ issueTokenTo?: string
177
+ gasPrice?: Number256
178
+ targetBlockHash?: string
179
+ }
180
+ assertType<Eq<keyof SignGrouplessDeployContractTxParams, keyof node.BuildGrouplessDeployContractTx>>()
181
+ export interface SignGrouplessExecuteScriptTxParams {
182
+ fromAddress: string
183
+ bytecode: string
184
+ attoAlphAmount?: Number256
185
+ tokens?: Token[]
186
+ gasPrice?: Number256
187
+ targetBlockHash?: string
188
+ gasEstimationMultiplier?: number
189
+ }
190
+ assertType<Eq<keyof SignGrouplessExecuteScriptTxParams, keyof node.BuildGrouplessExecuteScriptTx>>()
191
+ export type SignGrouplessTxParams =
192
+ | SignGrouplessTransferTxParams
193
+ | SignGrouplessDeployContractTxParams
194
+ | SignGrouplessExecuteScriptTxParams
195
+
162
196
  export type MessageHasher =
163
197
  | 'alephium' // Message is prefixed with 'Alephium signed message: ' before hashed with blake2b
164
198
  | 'sha256'
package/src/utils/sign.ts CHANGED
@@ -40,7 +40,7 @@ necc.utils.hmacSha256Sync = (key: Uint8Array, ...messages: Uint8Array[]): Uint8A
40
40
  export function sign(hash: string, privateKey: string, _keyType?: KeyType): string {
41
41
  const keyType = _keyType ?? 'default'
42
42
 
43
- if (keyType === 'default') {
43
+ if (keyType === 'default' || keyType === 'groupless') {
44
44
  const key = ec.keyFromPrivate(privateKey)
45
45
  const signature = key.sign(hash)
46
46
  return encodeSignature(signature)
@@ -54,7 +54,7 @@ export function verifySignature(hash: string, publicKey: string, signature: stri
54
54
  const keyType = _keyType ?? 'default'
55
55
 
56
56
  try {
57
- if (keyType === 'default') {
57
+ if (keyType === 'default' || keyType === 'groupless') {
58
58
  const key = ec.keyFromPublic(publicKey, 'hex')
59
59
  return key.verify(hash, signatureDecode(ec, signature))
60
60
  } else {