-
Notifications
You must be signed in to change notification settings - Fork 84
/
oracleDemoBsv20.ts
79 lines (73 loc) · 2.41 KB
/
oracleDemoBsv20.ts
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
import {
ByteString,
SmartContract,
Utils,
assert,
method,
prop,
slice,
} from 'scrypt-ts'
import { RabinPubKey, RabinSig, WitnessOnChainVerifier } from 'scrypt-ts-lib'
type Msg = {
marker: bigint // 1 byte, api marker
timestamp: bigint // 4 bytes LE
network: bigint // 1 byte, 1 for mainnet, 0 for testnet
outpoint: ByteString // 36 bytes, txid 32 bytes LE + vout 4 bytes LE
fungible: bigint // 1 byte, token type, 1 for BSV20, 0 for NFT
amt: bigint // 8 bytes LE
id: ByteString
}
export class OracleDemoBsv20 extends SmartContract {
@prop()
oraclePubKey: RabinPubKey
@prop()
inscriptionId: ByteString
@prop()
amt: bigint
constructor(
oraclePubKey: RabinPubKey,
inscriptionId: ByteString,
amt: bigint
) {
super(...arguments)
this.oraclePubKey = oraclePubKey
this.inscriptionId = inscriptionId
this.amt = amt
}
@method()
static parseMsg(msg: ByteString): Msg {
return {
marker: Utils.fromLEUnsigned(slice(msg, 0n, 1n)),
timestamp: Utils.fromLEUnsigned(slice(msg, 1n, 5n)),
network: Utils.fromLEUnsigned(slice(msg, 5n, 6n)),
outpoint: slice(msg, 6n, 42n),
fungible: Utils.fromLEUnsigned(slice(msg, 42n, 43n)),
amt: Utils.fromLEUnsigned(slice(msg, 43n, 51n)),
id: slice(msg, 51n),
}
}
@method()
public unlock(msg: ByteString, sig: RabinSig, tokenInputIndex: bigint) {
// retrieve token outpoint from prevouts
const outpoint = slice(
this.prevouts,
tokenInputIndex * 36n,
(tokenInputIndex + 1n) * 36n
)
// verify oracle signature
assert(
WitnessOnChainVerifier.verifySig(msg, sig, this.oraclePubKey),
'Oracle sig verify failed.'
)
// decode oracle data
const message = OracleDemoBsv20.parseMsg(msg)
// validate data
assert(message.marker == 4n, 'incorrect oracle message type')
assert(message.network == 0n, 'incorrect network')
assert(message.outpoint == outpoint, 'incorrect token outpoint')
assert(message.fungible == 1n, 'incorrect token type')
assert(message.amt >= this.amt, 'incorrect token amount')
assert(message.id == this.inscriptionId, 'incorrect inscription id')
// do other validations ...
}
}