@@ -216,3 +216,106 @@ impl fmt::Debug for Contract {
216
216
write ! ( f, "Contract({:?})" , Content :: from_bytes( self . as_bytes( ) ) . expect( "invariant" ) )
217
217
}
218
218
}
219
+
220
+ #[ cfg( test) ]
221
+ mod test {
222
+ use super :: * ;
223
+ use bitcoin:: hashes:: hex:: FromHex ;
224
+ use std:: str:: FromStr ;
225
+
226
+ #[ test]
227
+ fn test_json ( ) {
228
+ let correct = r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":8,"ticker":"USDt","version":0}"# ;
229
+ assert ! ( Contract :: from_bytes( correct. as_bytes( ) ) . is_ok( ) ) ;
230
+
231
+ let invalid = [
232
+ // missing precision
233
+ r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","ticker":"USDt","version":0}"# ,
234
+ // precision is string
235
+ r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":"no","ticker":"USDt","version":0}"# ,
236
+ // negative precision
237
+ r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":-2,"ticker":"USDt","version":0}"# ,
238
+ // too high precision
239
+ r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":9,"ticker":"USDt","version":0}"# ,
240
+ // missing ticker
241
+ r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":8,"version":0}"# ,
242
+ // ticker is int
243
+ r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":8,"ticker":8,"version":0}"# ,
244
+ // ticker too long
245
+ r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":8,"ticker":"USDtether","version":0}"# ,
246
+ ] ;
247
+ for json in & invalid {
248
+ assert ! ( Contract :: from_bytes( json. as_bytes( ) ) . is_err( ) , "invalid JSON was accepted: {}" , json) ;
249
+ }
250
+ }
251
+
252
+ #[ test]
253
+ fn test_tether ( ) {
254
+ let json = r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":8,"ticker":"USDt","version":0}"# ;
255
+ let tether_id = AssetId :: from_str ( "ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2" ) . unwrap ( ) ;
256
+ let tether_prevout = OutPoint :: from_str ( "9596d259270ef5bac0020435e6d859aea633409483ba64e232b8ba04ce288668:0" ) . unwrap ( ) ;
257
+ let tether_contract_hash = ContractHash :: from_hex ( "3c7f0a53c2ff5b99590620d7f6604a7a3a7bfbaaa6aa61f7bfc7833ca03cde82" ) . unwrap ( ) ;
258
+
259
+ let contract = Contract :: from_bytes ( json. as_bytes ( ) ) . unwrap ( ) ;
260
+ assert_eq ! ( contract. contract_hash( ) , tether_contract_hash) ;
261
+ assert_eq ! ( contract. asset_id( tether_prevout) , tether_id) ;
262
+
263
+ assert_eq ! ( contract. precision( ) , 8 ) ;
264
+ assert_eq ! ( contract. ticker( ) , "USDt" . to_owned( ) ) ;
265
+
266
+ assert_eq ! ( contract. property( "name" ) . unwrap( ) , Some ( "Tether USD" . to_owned( ) ) ) ;
267
+ assert_eq ! ( contract. property( "issuer_pubkey" ) . unwrap( ) ,
268
+ Some ( bitcoin:: PublicKey :: from_str( "0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904" ) . unwrap( ) ) ,
269
+ ) ;
270
+
271
+ #[ derive( Debug , PartialEq , Eq , Deserialize ) ]
272
+ struct Entity {
273
+ pub domain : String ,
274
+ }
275
+ assert_eq ! ( contract. property( "entity" ) . unwrap( ) ,
276
+ Some ( Entity { domain: "tether.to" . into( ) } ) ,
277
+ ) ;
278
+ }
279
+
280
+ #[ test]
281
+ fn test_cbor_wip ( ) {
282
+ #[ derive( Debug , PartialEq , Eq , Deserialize , Serialize ) ]
283
+ struct Entity {
284
+ pub domain : String ,
285
+ }
286
+ #[ derive( Debug , Serialize ) ]
287
+ struct ContractExtraContent {
288
+ pub entity : Entity ,
289
+ pub name : String ,
290
+ pub issuer_pubkey : bitcoin:: PublicKey ,
291
+ }
292
+
293
+ let extra = ContractExtraContent {
294
+ entity : Entity {
295
+ domain : "tether.to" . into ( ) ,
296
+ } ,
297
+ name : "Tether USD" . into ( ) ,
298
+ issuer_pubkey : "0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904" . parse ( ) . unwrap ( ) ,
299
+ } ;
300
+ let cbor_content: Vec < serde_cbor:: Value > = vec ! [
301
+ 8 . into( ) ,
302
+ "USDt" . to_owned( ) . into( ) ,
303
+ //TODO(stevenroose) optimize this as serde_cbor gets to_value
304
+ serde_cbor:: from_slice:: <serde_cbor:: Value >( & serde_cbor:: to_vec( & extra) . unwrap( ) ) . unwrap( ) ,
305
+ ] ;
306
+
307
+ // version byte
308
+ let mut buffer = vec ! [ 1u8 ] ;
309
+ serde_cbor:: to_writer ( & mut buffer, & cbor_content) . unwrap ( ) ;
310
+ let contract = Contract :: from_bytes ( & buffer) . unwrap ( ) ;
311
+
312
+ assert_eq ! ( contract. contract_hash( ) , ContractHash :: hash( & buffer) ) ;
313
+
314
+ assert_eq ! ( contract. precision( ) , 8 ) ;
315
+ assert_eq ! ( contract. ticker( ) , "USDt" . to_owned( ) ) ;
316
+
317
+ assert_eq ! ( contract. property( "name" ) . unwrap( ) , Some ( extra. name) ) ;
318
+ assert_eq ! ( contract. property( "issuer_pubkey" ) . unwrap( ) , Some ( extra. issuer_pubkey) ) ;
319
+ assert_eq ! ( contract. property( "entity" ) . unwrap( ) , Some ( extra. entity) ) ;
320
+ }
321
+ }
0 commit comments