Skip to content
This repository was archived by the owner on Jan 19, 2026. It is now read-only.

Commit cb4d3e5

Browse files
authored
[BFS-775] Remove blake2b hashing and refactor (#73)
1 parent 0404660 commit cb4d3e5

10 files changed

Lines changed: 111 additions & 105 deletions

File tree

docs/README.rfq.md

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ At the root of your working directory, create `rfq-contracts.json` and add the c
4141
4242
### Initializing the Client
4343
```python
44-
# Seed phrase (mnemonic) of the wallet
44+
# Seed phrase (mnemonic) of the wallet (currently supports only ED25519)
4545
TEST_ACCT_PHRASE = "wallet seed phrase"
4646
# RPC URL of the chain
4747
TEST_NETWORK = "https://fullnode.mainnet.sui.io:443"
@@ -60,7 +60,10 @@ rfq_client = RFQClient(wallet=wallet, url=TEST_NETWORK, rfq_contracts=rfq_contra
6060

6161
```
6262

63-
### Creating and Signing a Quote
63+
### Creating and Signing a Quote
64+
65+
#### Supported wallets (No hashing required):
66+
- `ED25519`
6467

6568
#### Parameters:
6669
- `vault` (str): On-chain vault object ID.
@@ -75,7 +78,7 @@ rfq_client = RFQClient(wallet=wallet, url=TEST_NETWORK, rfq_contracts=rfq_contra
7578

7679
```python
7780

78-
# To only create the quote use
81+
# To only create the quote, use
7982
quote = rfq_client.create_quote(
8083
vault="0x67399451f127894ee0f9ff7182cbe914008a0197a97b54e86226d1c33635c368",
8184
quote_id="quote-123",
@@ -84,10 +87,13 @@ quote = rfq_client.create_quote(
8487
token_out_amount=200000000,
8588
token_in_type="0x2::sui::SUI",
8689
token_out_type="0x2::example::TOKEN",
87-
created_at_utc_ms=1699765400,
90+
expired_at_utc_ms=1699765400,
8891
created_at_utc_ms=1698765400,
8992
)
9093

94+
# To sign the created quote , use
95+
quote.sign(rfq_client.wallet)
96+
9197
#To create quote and sign it at the same time, use
9298
quote, signature = rfq_client.create_and_sign_quote(
9399
vault="0x67399451f127894ee0f9ff7182cbe914008a0197a97b54e86226d1c33635c368",
@@ -97,12 +103,16 @@ quote, signature = rfq_client.create_and_sign_quote(
97103
token_out_amount=200000000,
98104
token_in_type="0x2::sui::SUI",
99105
token_out_type="0x2::example::TOKEN",
100-
created_at_utc_ms=1699765400,
106+
expired_at_utc_ms=1699765400,
101107
created_at_utc_ms=1698765400,
102108
)
103109
```
104110

105111
### Depositing Tokens into a Vault
112+
113+
#### Supported wallets (blake2b hashing required, since its a sui transaction):
114+
- `ED25519`
115+
106116
```python
107117
rfq_client.deposit_in_vault(
108118
vault="0x40923d059eae6ccbbb91ac9442b80b9bec8262122a5756d96021e34cf33f0b1d",
@@ -112,6 +122,10 @@ rfq_client.deposit_in_vault(
112122
```
113123

114124
### Withdrawing Tokens from a Vault
125+
126+
#### Supported wallets (blake2b hashing required, since its a sui transaction):
127+
- `ED25519`
128+
115129
```python
116130
rfq_client.withdraw_from_vault(
117131
vault="0x40923d059eae6ccbbb91ac9442b80b9bec8262122a5756d96021e34cf33f0b1d",
@@ -121,6 +135,10 @@ rfq_client.withdraw_from_vault(
121135
```
122136

123137
### Creating a new Vault
138+
139+
#### Supported wallets (blake2b hashing required, since its a sui transaction):
140+
- `ED25519`
141+
124142
```python
125143
rfq_client.create_vault(
126144
manager="0x40923d059eae6ccbbb91ac9442b80b9bec8262122a5756d96021e34cf33f0b1d",
@@ -137,7 +155,7 @@ Initializes the RFQClient.
137155
- `url` (str): RPC URL of the chain node.
138156
- `rfq_contracts` (RFQContracts): Instance of RFQContracts.
139157

140-
#### `create_quote(...) -> Quote`</br>`sign_quote(quote: Quote) -> str`</br> `create_and_sign_quote(...) -> Tuple[Quote, str]`
158+
#### `create_quote(...) -> Quote`</br> `create_and_sign_quote(...) -> Tuple[Quote, str]`
141159

142160

143161
Creates or/and signs a quote.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "bluefin_v2_client_sui"
3-
version = "1.1.5"
3+
version = "1.1.6"
44
description = "Library to interact with Bluefin exchange protocol including its off-chain api-gateway and on-chain contracts"
55
readme = "README.md"
66
requires-python = ">=3.8"

src/bluefin_rfq_client/quote.py

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
from sui_utils.bcs import BCSSerializer
2+
from sui_utils import *
33
from typing import Self
44

55

@@ -43,9 +43,9 @@ def __init__(
4343
self.token_out_type = token_out_type
4444
self.expires_at = expires_at
4545
self.created_at = created_at
46+
self.signer = Signer()
4647

47-
@staticmethod
48-
def get_bcs_serialized_quote(quote: Self) -> bytes:
48+
def get_bcs_serialized_quote(self) -> bytes:
4949
"""
5050
Returns BCS serialized bytes of the quote.
5151
@@ -57,15 +57,32 @@ def get_bcs_serialized_quote(quote: Self) -> bytes:
5757
serializer = BCSSerializer()
5858

5959
# Apply BCS serialization to the Quote in correct order
60-
serializer.serialize_address(quote.vault)
61-
serializer.serialize_str(quote.id)
62-
serializer.serialize_address(quote.taker)
63-
serializer.serialize_u64(quote.token_in_amount)
64-
serializer.serialize_u64(quote.token_out_amount)
65-
serializer.serialize_str(quote.token_in_type)
66-
serializer.serialize_str(quote.token_out_type)
67-
serializer.serialize_u64(quote.expires_at)
68-
serializer.serialize_u64(quote.created_at)
60+
serializer.serialize_address(self.vault)
61+
serializer.serialize_str(self.id)
62+
serializer.serialize_address(self.taker)
63+
serializer.serialize_u64(self.token_in_amount)
64+
serializer.serialize_u64(self.token_out_amount)
65+
serializer.serialize_str(self.token_in_type)
66+
serializer.serialize_str(self.token_out_type)
67+
serializer.serialize_u64(self.expires_at)
68+
serializer.serialize_u64(self.created_at)
6969

7070
return serializer.get_bytes()
71+
72+
def sign(self, wallet: SuiWallet) -> bytes:
73+
serializedBytes = self.get_bcs_serialized_quote()
74+
signature = self.signer.sign_bytes(serializedBytes,wallet.privateKeyBytes)
75+
scheme = wallet.getKeyScheme()
76+
77+
signatureBytes = bytearray()
78+
if scheme == WALLET_SCHEME.ED25519:
79+
signatureBytes.append(0)
80+
else:
81+
signatureBytes.append(1)
82+
83+
signatureBytes.extend(signature)
84+
signatureBytes.extend(wallet.publicKeyBytes)
85+
86+
return signatureBytes
87+
7188

src/bluefin_rfq_client/rfq.py

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,6 @@ def create_quote(
7777
expires_at=expires_at_utc_ms,
7878
created_at=created_at_utc_ms,
7979
)
80-
81-
def sign_quote(self, quote: Quote) -> str:
82-
"""
83-
Signs the input Quote instance.
84-
85-
:param quote (Quote): instance of Quote class.
86-
87-
Returns:
88-
Signature in hex format.
89-
"""
90-
bcs_serialized_bytes = Quote.get_bcs_serialized_quote(quote)
91-
92-
# Sign bcs serialized quote bytes
93-
signature = self.wallet.sign_personal_msg(bcs_serialized_bytes)
94-
95-
return signature.hex()
9680

9781
def create_and_sign_quote(
9882
self,
@@ -141,10 +125,7 @@ def create_and_sign_quote(
141125
created_at=created_at_utc_ms,
142126
)
143127

144-
bcs_serialized_bytes = Quote.get_bcs_serialized_quote(quote)
145-
146-
# Sign bcs serialized quote bytes
147-
signature = self.wallet.sign_personal_msg(bcs_serialized_bytes)
128+
signature = quote.sign(self.wallet)
148129

149130
return (quote, signature.hex())
150131

src/sui_utils/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
from .utilities import *
33
from .rpc import *
44
from .signer import *
5-
from .bcs import *
5+
from .bcs import *
6+
from .enumerations import *

src/sui_utils/account.py

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import nacl
2-
import nacl.signing
1+
from .enumerations import WALLET_SCHEME
32
from .utilities import *
43
import base64
54
from .bcs import *
65

76

87
class SuiWallet:
9-
def __init__(self, seed="", privateKey=""):
8+
def __init__(self, seed="", privateKey="",scheme:WALLET_SCHEME = WALLET_SCHEME.ED25519):
109
if seed == "" and privateKey == "":
1110
return "Error"
1211
if seed != "":
@@ -16,6 +15,7 @@ def __init__(self, seed="", privateKey=""):
1615
self.publicKeyBase64 = base64.b64encode(self.publicKey.ToBytes()[1:])
1716
self.privateKeyBase64 = base64.b64encode(self.privateKey.ToBytes()[1:])
1817
self.privateKeyBytes = self.privateKey.ToBytes()
18+
self.scheme = scheme
1919

2020
elif privateKey != "":
2121
self.privateKey = privateKey
@@ -24,12 +24,13 @@ def __init__(self, seed="", privateKey=""):
2424
self.publicKeyBase64 = base64.b64encode(self.publicKey.ToBytes()[1:])
2525
self.privateKeyBase64 = base64.b64encode(binascii.unhexlify(self.privateKey)[1:])
2626
self.privateKeyBytes = binascii.unhexlify(self.privateKey)
27+
self.scheme = scheme
2728

2829
else:
2930
return "error"
3031

3132

32-
self.publicKeyBytes = self.publicKey.ToBytes()
33+
self.publicKeyBytes = self.publicKey.ToBytes()[1:]
3334
self.address = getAddressFromPublicKey(self.publicKey)
3435

3536
def getPublicKey(self):
@@ -48,29 +49,7 @@ def getPrivateKey(self):
4849
def getUserAddress(self):
4950
return self.address
5051

51-
def sign_personal_msg(self, serialized_bytes: bytearray):
52-
serializer = BCSSerializer()
53-
# this function adds len as an Unsigned Little Endian Base 128 similar to mysten SDK
54-
serializer.serialize_uint8_array(list(serialized_bytes))
55-
serialized_bytes = serializer.get_bytes()
56-
57-
# Add personal message intent bytes
58-
intent = bytearray()
59-
intent.extend([ 3, 0, 0]) # Intent scope for personal message
60-
61-
# Combine the intent and msg_bytes
62-
intent = intent + serialized_bytes
63-
64-
# Combine blake2b hash
65-
blake2bHash = hashlib.blake2b(intent, digest_size=32).digest()
66-
67-
# Sign the hash
68-
signature = nacl.signing.SigningKey(self.privateKeyBytes).sign(blake2bHash)[:64]
69-
70-
71-
ED25519_SCHEME_FLAG = 0
72-
serializer = BCSSerializer()
73-
serializer.serialize_u8(ED25519_SCHEME_FLAG)
74-
75-
# Construct Signature in accurate format (scheme + signature + publicKey)
76-
return serializer.get_bytes()+ signature + self.publicKeyBytes[1:]
52+
def getKeyScheme(self):
53+
return self.scheme
54+
55+

src/sui_utils/bcs.py

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import struct
2+
from .utilities import *
23

34

45
class BCSSerializer:
@@ -132,21 +133,3 @@ def hex_to_byte_array(hex_address: str) -> bytearray:
132133
except ValueError as e:
133134
raise ValueError(f"Invalid hex string: {e}")
134135

135-
def decimal_to_bcs(num):
136-
# Initialize an empty list to store the BCS bytes
137-
bcs_bytes = []
138-
while num > 0:
139-
# Take the last 7 bits of the number
140-
bcs_byte = num & 0x7F
141-
142-
# Set the most significant bit (MSB) to 1 if there are more bytes to follow
143-
if num > 0x7F:
144-
bcs_byte |= 0x80
145-
146-
# Append the BCS byte to the list
147-
bcs_bytes.append(bcs_byte)
148-
149-
# Right-shift the number by 7 bits to process the next portion
150-
num >>= 7
151-
152-
return bcs_bytes

src/sui_utils/enumerations.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from enum import Enum
2+
3+
4+
class WALLET_SCHEME(Enum):
5+
ED25519 = "ED25519"
6+
Secp256k1 = "Secp256k1" #not supportted currently

0 commit comments

Comments
 (0)