Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ near-jsonrpc-primitives.workspace = true
regex.workspace = true
thiserror.workspace = true
hex.workspace = true
aurora-sdk-macros = { path = "macros" }

[dev-dependencies]
near-contract-standards.workspace = true
Expand Down
14 changes: 14 additions & 0 deletions sdk/macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "aurora-sdk-macros"
description = "Procedural macros for Aurora SDK"
version = "0.1.0"
edition = "2021"

[lib]
proc-macro = true

[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "2.0", features = ["full", "extra-traits"] }
serde_json = "1.0"
153 changes: 153 additions & 0 deletions sdk/macros/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Aurora SDK Macros

This crate contains procedural macros for Aurora SDK.

## ContractMethod Derive Macro

The `ContractMethod` macro automatically implements the `ContractMethod` trait
for structs, simplifying the creation of contract methods.

### Usage

```rust
use aurora_sdk_rs::ContractMethod;
use serde::{Serialize, Deserialize};

#[derive(ContractMethod, Serialize, Deserialize)]
#[contract_method(
method = "get_user_balance",
response = u128,
serialize_as = "json"
)]
pub struct GetUserBalance {
#[contract_param]
pub user_id: String,
pub internal_data: u64,
}
```

### Attributes

#### Main attribute `#[contract_method(...)]`

Required for all structs with the following parameters:

- `method` - contract method name (string)
- `response` - method response type
- `serialize_as` - parameter serialization method: `"json"` or `"borsh"`
(defaults to `"borsh"`)

#### Field attribute `#[contract_param]`

Optional attribute for selecting a field for serialization:

- If the attribute is specified on one field - only this field is serialized
- If the attribute is not specified on any field - empty parameters are returned
- Can only be specified on one field (macro limitation)
- **Special case**: Fields of type `Vec<u8>` are returned as-is without
serialization

### Examples

#### Selective serialization with JSON

```rust
#[derive(ContractMethod, Serialize, Deserialize)]
#[contract_method(
method = "get_user_data",
response = UserData,
serialize_as = "json"
)]
pub struct GetUserData {
#[contract_param]
pub user_id: String,
pub cache_timestamp: u64,
pub debug_info: String,
}
```

#### Vec<u8> field (returned as-is)

```rust
#[derive(ContractMethod)]
#[contract_method(
method = "submit_raw_data",
response = (),
serialize_as = "json"
)]
pub struct SubmitRawData {
#[contract_param]
pub raw_data: Vec<u8>,
pub metadata: String,
}
```

#### Selective serialization with Borsh

```rust
#[derive(ContractMethod, borsh::BorshSerialize, borsh::BorshDeserialize)]
#[contract_method(
method = "transfer",
response = (),
serialize_as = "borsh"
)]
pub struct Transfer {
#[contract_param]
pub transfer_args: TransferArgs,
pub metadata: String,
}
```

#### Unit struct (empty parameters)

```rust
#[derive(ContractMethod)]
#[contract_method(
method = "get_version",
response = String,
serialize_as = "json"
)]
pub struct GetVersion;
```

#### Struct without parameters

```rust
#[derive(ContractMethod, Serialize, Deserialize)]
#[contract_method(
method = "ping",
response = (),
serialize_as = "json"
)]
pub struct Ping {
pub timestamp: u64,
pub debug: String,
}
```

### Macro behavior

1. **With `#[contract_param]` attribute on `Vec<u8>`**: Field is returned as-is
(without serialization)
2. **With `#[contract_param]` attribute on other types**: Serialized according
to `serialize_as`
3. **Without attributes**: Returns empty vector `Vec::new()`
4. **Unit structs**: Always return empty vector
5. **Multiple fields with `#[contract_param]`**: Compilation error

### What the macro generates

The macro automatically implements the `ContractMethod` trait with the following
methods:

- `method_name(&self) -> &'static str` - returns the method name
- `params(&self) -> Result<Vec<u8>, std::io::Error>` - returns parameters
according to the logic above

### Requirements

- For `serialize_as = "json"`: selected field must implement `serde::Serialize`
(except `Vec<u8>`)
- For `serialize_as = "borsh"`: selected field must implement
`borsh::BorshSerialize` (except `Vec<u8>`)
- Response type must implement `ContractMethodResponse`
Loading
Loading