Skip to content
Open
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
2 changes: 1 addition & 1 deletion .swcrc
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@
},
"baseUrl": "."
}
}
}
32 changes: 32 additions & 0 deletions docs/output-schemas-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,38 @@ interface CommandOutputSpec {

`type` is `"FUNGIBLE"` or `"NFT"`. For FT entries `amount` is present; for NFT entries `serialNumber` is present. `hasMore: true` indicates more results exist — use `--show-all` to fetch all pages. Token name and symbol are fetched from the mirror node.

#### `token reject-airdrop`

**Output**:

```json
{
"transactionId": "0.0.123@1700000000.123456789",
"ownerAccountId": "0.0.1234",
"network": "testnet",
"rejected": [
{
"tokenId": "0.0.5678",
"tokenName": "FungibleToken",
"tokenSymbol": "FT",
"senderId": "0.0.9999",
"type": "FUNGIBLE",
"amount": 1000
},
{
"tokenId": "0.0.5679",
"tokenName": "MyNFT",
"tokenSymbol": "NFT",
"senderId": "0.0.9999",
"type": "NFT",
"serialNumber": 42
}
]
}
```

`rejected` contains the airdrops that were rejected, selected by `--index` from the `pending-airdrops` list. `type` is `"FUNGIBLE"` or `"NFT"`. For FT entries `amount` is present; for NFT entries `serialNumber` is present. Maximum 10 items per transaction (Hedera limit). Token name and symbol are fetched from the mirror node.

#### `token transfer-ft`

**Output**:
Expand Down
6 changes: 6 additions & 0 deletions src/core/services/token/token-service.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
TokenCreateTransaction,
TokenDeleteTransaction,
TokenMintTransaction,
TokenRejectTransaction,
TransferTransaction,
} from '@hashgraph/sdk';
import type {
Expand All @@ -23,6 +24,7 @@ import type {
TokenCreateParams,
TokenDeleteParams,
TokenMintParams,
TokenRejectAirdropParams,
TokenTransferParams,
} from '@/core/types/token.types';

Expand Down Expand Up @@ -80,4 +82,8 @@ export interface TokenService {
createAirdropNftTransaction(
params: TokenAirdropNftParams,
): TokenAirdropTransaction;

createRejectAirdropTransaction(
params: TokenRejectAirdropParams,
): TokenRejectTransaction;
}
26 changes: 26 additions & 0 deletions src/core/services/token/token-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
TokenCreateParams,
TokenDeleteParams,
TokenMintParams,
TokenRejectAirdropParams,
TokenTransferParams,
} from '@/core/types/token.types';
import type { TokenService } from './token-service.interface';
Expand All @@ -35,6 +36,7 @@ import {
TokenDeleteTransaction,
TokenId,
TokenMintTransaction,
TokenRejectTransaction,
TokenSupplyType,
TransferTransaction,
} from '@hashgraph/sdk';
Expand Down Expand Up @@ -441,6 +443,30 @@ export class TokenServiceImpl implements TokenService {
return tx;
}

createRejectAirdropTransaction(
params: TokenRejectAirdropParams,
): TokenRejectTransaction {
const { ownerAccountId, items } = params;
const owner = AccountId.fromString(ownerAccountId);

this.logger.debug(
`[TOKEN SERVICE] Creating reject transaction: ${items.length} item(s) for owner ${ownerAccountId}`,
);

const tx = new TokenRejectTransaction().setOwnerId(owner);

for (const item of items) {
const tokenId = TokenId.fromString(item.tokenId);
if (item.serialNumber !== undefined) {
tx.addNftId(new NftId(tokenId, item.serialNumber));
} else {
tx.addTokenId(tokenId);
}
}

return tx;
}

/**
* Process custom fees and convert them to Hedera CustomFee objects
*/
Expand Down
10 changes: 10 additions & 0 deletions src/core/types/token.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,13 @@ export interface TokenAirdropNftParams {
senderAccountId: string;
transfers: TokenAirdropNftTransfer[];
}

export interface RejectAirdropItem {
tokenId: string;
serialNumber?: number; // undefined for FT
}

export interface TokenRejectAirdropParams {
ownerAccountId: string;
items: RejectAirdropItem[];
}
47 changes: 47 additions & 0 deletions src/plugins/token/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,53 @@ hcli token airdrop-nft \

**Implementation:** [`src/plugins/token/commands/airdrop-nft/handler.ts`](./commands/airdrop-nft/handler.ts)

### Token Reject Airdrop

Reject one or more pending token airdrops (FT or NFT). Rejected tokens are returned to the treasury. Custom fees are waived. Use `pending-airdrops` first to list available airdrops and their indices.

```bash
# List pending airdrops
hcli token pending-airdrops --account my-wallet

# Reject first pending airdrop
hcli token reject-airdrop \
--account my-wallet \
--index 1

# Reject multiple airdrops (FT and/or NFT)
hcli token reject-airdrop \
--account my-wallet \
--index 1,2,3

# With explicit signing key
hcli token reject-airdrop \
--account my-wallet \
--index 1 \
--from 0.0.5678:302e020100300506032b657004220420...

# Batch mode
hcli token reject-airdrop \
--account my-wallet \
--index 1 \
--batch my-batch
```

**Parameters:**

- `--account` / `-a`: Receiver account ID or alias - **Required**
- `--index` / `-i`: 1-based index(es) from `pending-airdrops` list. Comma-separated for multiple: `1,2,3` - **Required**
- `--from` / `-f`: Signing account credential (alias or account-id:private-key pair) - **Optional** (defaults to operator)
- `--key-manager` / `-k`: Key manager type (optional, defaults to config setting)
- `local` or `local_encrypted`

**Notes:**

- Maximum 10 airdrops per transaction (Hedera limit)
- Supports both fungible tokens (FT) and NFTs in a single transaction
- Batch support: pass `--batch <batch-name>` to queue the transaction for batch execution

**Implementation:** [`src/plugins/token/commands/reject-airdrop/handler.ts`](./commands/reject-airdrop/handler.ts)

### Token Transfer NFT

Transfer one or more NFTs from one account to another.
Expand Down
1 change: 1 addition & 0 deletions src/plugins/token/__tests__/unit/helpers/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export const makeTokenServiceMock = (
createDeleteTransaction: jest.fn(),
createAirdropFtTransaction: jest.fn(),
createAirdropNftTransaction: jest.fn(),
createRejectAirdropTransaction: jest.fn(),
...overrides,
});

Expand Down
Loading
Loading