-
Notifications
You must be signed in to change notification settings - Fork 302
Expand file tree
/
Copy pathofcToken.ts
More file actions
151 lines (131 loc) · 3.68 KB
/
ofcToken.ts
File metadata and controls
151 lines (131 loc) · 3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/**
* @prettier
*/
import { OfcTokenConfig } from '@bitgo/statics';
import * as bolt11 from 'bolt11';
import { isString } from 'lodash';
import {
BitGoBase,
CoinConstructor,
SignTransactionOptions as BaseSignTransactionOptions,
SignedTransaction,
ITransactionRecipient,
} from '../';
import { Ofc } from './ofc';
export interface SignTransactionOptions extends BaseSignTransactionOptions {
txPrebuild: {
payload: string;
};
prv: string;
}
export { OfcTokenConfig };
const publicIdRegex = /^[a-f\d]{32}$/i;
function isBolt11Invoice(value: unknown): value is string {
if (!isString(value)) {
return false;
}
try {
bolt11.decode(value);
return true;
} catch (_e) {
return false;
}
}
export class OfcToken extends Ofc {
public readonly tokenConfig: OfcTokenConfig;
constructor(bitgo: BitGoBase, tokenConfig: OfcTokenConfig) {
super(bitgo);
this.tokenConfig = tokenConfig;
}
get coin() {
return this.tokenConfig.coin;
}
get decimalPlaces() {
return this.tokenConfig.decimalPlaces;
}
get name() {
return this.tokenConfig.name;
}
get backingCoin() {
return this.tokenConfig.backingCoin;
}
get isFiat() {
return this.tokenConfig.isFiat;
}
getChain() {
return this.type;
}
getFullName() {
return this.name;
}
getBaseFactor() {
return String(Math.pow(10, this.decimalPlaces));
}
public get type() {
return this.tokenConfig.type;
}
checkRecipient(recipient: ITransactionRecipient): void {
if (isBolt11Invoice(recipient.address)) {
// amount for bolt11 invoices is either 'invoice' or a non-zero bigint
if (recipient.amount === 'invoice') {
return;
}
// try to parse the amount as a bigint
let amount: bigint;
try {
amount = BigInt(recipient.amount);
} catch (e) {
throw new Error(
`invalid argument ${recipient.amount} for amount - lightning invoice amount must be >= 0 or 'invoice'`
);
}
if (amount > 0n) {
return;
}
throw new Error(`invalid argument for amount - lightning invoice amount must be a non-zero bigint or 'invoice'`);
}
super.checkRecipient(recipient);
}
/**
* Flag for sending value of 0
* @returns {boolean} True if okay to send 0 value, false otherwise
*/
valuelessTransferAllowed() {
return false;
}
static createTokenConstructor(config: OfcTokenConfig): CoinConstructor {
return (bitgo: BitGoBase) => new OfcToken(bitgo, config);
}
/**
* Assemble keychain and half-sign prebuilt transaction
* @param params
* @returns {Promise<SignedTransaction>}
*/
async signTransaction(params: SignTransactionOptions): Promise<SignedTransaction> {
const txPrebuild = params.txPrebuild;
const payload = txPrebuild.payload;
const signatureBuffer = (await this.signMessage(params, payload)) as any;
const signature: string = signatureBuffer.toString('hex');
return { halfSigned: { payload, signature } } as any;
}
/**
* Check if an address is valid for this ofc token.
*
* These addresses are either bg-<publicid>, where public id is the internal address to send to,
* or are an address which is valid on the backing coin of this ofc token.
* @param address address to check for validity
*/
isValidAddress(address?: string): boolean {
if (!isString(address)) {
return false;
}
if (address.startsWith('bg-')) {
const parts = address.split('-');
const accountId = parts[1];
return parts.length === 2 && publicIdRegex.test(accountId);
} else {
const backingCoin = this.bitgo.coin(this.backingCoin);
return backingCoin.isValidAddress(address);
}
}
}