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
52 changes: 52 additions & 0 deletions .github/workflows/aztec-testnet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Aztec Testnet Network gRPC

on:
workflow_dispatch:
push:
branches: [ main, dev ]
paths:
- 'js-aztec-testnet/src/**'
- 'js-aztec-testnet/package.json'
- 'js-aztec-testnet/package-lock.json'
- 'js-aztec-testnet/tsconfig.json'
- 'Dockerfile.aztec-testnet-grpc'
- 'protos/**'
- '.github/workflows/aztec-testnet.yml'
- '.github/actions/docker/**'
pull_request:
branches: [ main, dev ]
paths:
- 'js-aztec-testnet/src/**'
- 'js-aztec-testnet/package.json'
- 'js-aztec-testnet/package-lock.json'
- 'js-aztec-testnet/tsconfig.json'
- 'Dockerfile.aztec-testnet-grpc'
- 'protos/**'
- '.github/workflows/aztec-testnet.yml'
- '.github/actions/docker/**'
release:
types: [published, created]

env:
DOCKER_IMAGE: trainprotocol/solver-aztec-testnet-grpc
NODE_VERSION: 22

jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Docker build and push
id: docker
uses: ./.github/actions/docker
with:
context: .
file: Dockerfile.aztec-testnet-grpc
docker-image: ${{ env.DOCKER_IMAGE }}
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
build-args: ""
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*.sln.docstates
appsettings.Local.json
dbsettings.Local.json
local-secrets.json
.vault-data
.claude/settings.json
.claude/settings.local.json
Expand Down
34 changes: 34 additions & 0 deletions Dockerfile.aztec-testnet-grpc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
FROM ubuntu:24.04 AS builder

RUN apt-get update && apt-get install -y curl python3 make g++ && \
curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \
apt-get install -y nodejs && \
rm -rf /var/lib/apt/lists/*

WORKDIR /app/js-aztec-testnet

COPY js-aztec-testnet/package*.json ./
RUN --mount=type=cache,id=npm-aztec-testnet,target=/root/.npm npm ci --ignore-scripts

COPY js-aztec-testnet/ .
COPY protos/ /app/protos/
RUN npm run build

FROM ubuntu:24.04 AS final

RUN apt-get update && apt-get install -y curl && \
curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \
apt-get install -y nodejs && \
apt-get purge -y curl && apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*

WORKDIR /app/js-aztec-testnet
COPY --from=builder /app/js-aztec-testnet/node_modules ./node_modules
COPY --from=builder /app/js-aztec-testnet/dist ./dist
COPY --from=builder /app/js-aztec-testnet/src/contracts ./contracts
COPY --from=builder /app/js-aztec-testnet/package.json ./package.json
COPY --from=builder /app/protos /app/protos

EXPOSE 8080

CMD ["node", "dist/server.js"]
3,300 changes: 3,300 additions & 0 deletions csharp/contracts/Train.aztec.testnet.abi.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions csharp/src/AdminAPI/Endpoints/WalletEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ private static async Task<IResult> CreateAsync(
IGrpcNetworkService runtimeService,
[FromBody] CreateWalletRequest request)
{
// Resolve network for this type
// Resolve network: prefer the explicit NetworkSlug scope, fall back to first network of this type
var networks = await networkRepository.GetAllAsync(null);
var network = networks.FirstOrDefault(n => n.Type.Name == request.NetworkType);
var network = !string.IsNullOrWhiteSpace(request.NetworkSlug)
? networks.FirstOrDefault(n => n.Slug == request.NetworkSlug)
: networks.FirstOrDefault(n => n.Type.Name == request.NetworkType);

// Address provided (whitelisted or duplicate of existing wallet)
if (!string.IsNullOrWhiteSpace(request.Address))
Expand Down
78 changes: 52 additions & 26 deletions csharp/src/AdminPanel.Client/Pages/Bridge.razor
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,8 @@
<option value="">Network</option>
@foreach (var slug in sourceNetworkSlugs)
{
var net = networks.First(n => n.Slug == slug);
<option value="@slug">@net.DisplayName</option>
var net = networks.FirstOrDefault(n => n.Slug == slug);
<option value="@slug">@(net?.DisplayName ?? slug)</option>
}
</select>
</div>
Expand Down Expand Up @@ -351,8 +351,8 @@
<option value="">Network</option>
@foreach (var slug in destNetworkSlugs)
{
var net = networks.First(n => n.Slug == slug);
<option value="@slug">@net.DisplayName</option>
var net = networks.FirstOrDefault(n => n.Slug == slug);
<option value="@slug">@(net?.DisplayName ?? slug)</option>
}
</select>
</div>
Expand Down Expand Up @@ -712,7 +712,7 @@
private const string StarknetNetworkTypeName = "starknet";
private const string TronNetworkTypeName = "tron";
private const string SolanaNetworkTypeName = "solana";
private const string HardcodedAztecUserAddress = "0x2510cf68508189642120d8c4bc58c75199614b53644e83ae38da4de8c2057875";
private string? aztecAddress; // Aztec (Azguard)

// Wallet state — separate addresses per wallet type
private string? walletAddress; // EVM (MetaMask)
Expand Down Expand Up @@ -801,6 +801,8 @@
networks = await NetworkService.GetAllAsync();
routes = await RouteService.GetAllAsync(["Active"]);
sourceNetworkSlugs = OrderNetworkSlugs(routes.Select(r => r.Source.Network.Slug).Distinct());
StateHasChanged();
await Task.Yield();
}
catch (Exception ex)
{
Expand Down Expand Up @@ -843,6 +845,20 @@
}
catch { /* Solflare not available */ }

try
{
var restored = await JS.InvokeAsync<WalletConnectResult?>("aztecUtils.restoreSession");
if (restored != null && !string.IsNullOrEmpty(restored.Address))
aztecAddress = restored.Address;
else
{
var existing = await JS.InvokeAsync<string?>("aztecUtils.getAddress");
if (!string.IsNullOrEmpty(existing))
aztecAddress = existing;
}
}
catch { /* Azguard not available */ }

// Restore active swap from localStorage
await RestoreSwapStateAsync();
}
Expand Down Expand Up @@ -1013,7 +1029,8 @@
var types = new HashSet<string>();
void AddType(string slug)
{
if (string.IsNullOrEmpty(slug) || IsAztecNetwork(slug)) return;
if (string.IsNullOrEmpty(slug)) return;
if (IsAztecNetwork(slug)) { types.Add("aztec"); return; }
if (IsStarknetNetwork(slug)) types.Add("starknet");
else if (IsTronNetwork(slug)) types.Add("tron");
else if (IsSolanaNetwork(slug)) types.Add("solana");
Expand Down Expand Up @@ -1082,6 +1099,21 @@
}
}

private async Task ConnectAztecWalletAsync()
{
error = null;
try
{
var chainId = networks.FirstOrDefault(n => n.Slug == fromNetworkSlug)?.ChainId ?? "0";
var result = await JS.InvokeAsync<WalletConnectResult>("aztecUtils.connect", chainId);
aztecAddress = result.Address;
}
catch (Exception ex)
{
error = ex.Message;
}
}

private async Task ConnectWalletForNetworkAsync(string networkSlug)
{
// Toggle: if already connected, disconnect
Expand All @@ -1092,7 +1124,8 @@
return;
}

if (IsStarknetNetwork(networkSlug)) await ConnectStarknetWalletAsync();
if (IsAztecNetwork(networkSlug)) await ConnectAztecWalletAsync();
else if (IsStarknetNetwork(networkSlug)) await ConnectStarknetWalletAsync();
else if (IsTronNetwork(networkSlug)) await ConnectTronWalletAsync();
else if (IsSolanaNetwork(networkSlug)) await ConnectSolanaWalletAsync();
else await ConnectEvmWalletAsync();
Expand All @@ -1103,7 +1136,12 @@
error = null;
try
{
if (IsStarknetNetwork(networkSlug))
if (IsAztecNetwork(networkSlug))
{
await JS.InvokeAsync<bool>("aztecUtils.disconnect");
aztecAddress = null;
}
else if (IsStarknetNetwork(networkSlug))
{
await JS.InvokeAsync<bool>("starknetUtils.disconnect");
starknetAddress = null;
Expand Down Expand Up @@ -1507,23 +1545,7 @@

if (IsAztecNetwork(fromNetworkSlug))
{
if (string.IsNullOrWhiteSpace(buildResult.Data))
{
error = "Aztec user lock payload is empty.";
return;
}

var publishRequest = new PublishAztecUserLockRequest
{
NetworkSlug = fromNetworkSlug,
SenderAddress = HardcodedAztecUserAddress,
FunctionInteractionJson = buildResult.Data,
ContractAddress = buildResult.ContractAddress,
ToAddress = buildResult.ToAddress,
};

var publishResult = await TransactionBuilderService.PublishAztecUserLockAsync(publishRequest);
lockTxHash = publishResult.TxHash;
lockTxHash = await SendTransactionViaWalletAsync(fromNetworkSlug, buildResult.ToAddress, buildResult.Data, buildResult.Amount);
}
else if (IsStarknetNetwork(fromNetworkSlug))
{
Expand Down Expand Up @@ -2024,7 +2046,7 @@

private string? GetWalletForNetwork(string networkSlug)
{
if (IsAztecNetwork(networkSlug)) return HardcodedAztecUserAddress;
if (IsAztecNetwork(networkSlug)) return aztecAddress;
if (IsStarknetNetwork(networkSlug)) return starknetAddress;
if (IsTronNetwork(networkSlug)) return tronAddress;
if (IsSolanaNetwork(networkSlug)) return solanaAddress;
Expand All @@ -2033,6 +2055,7 @@

private string GetWalletLabel(string networkSlug)
{
if (IsAztecNetwork(networkSlug)) return "Azguard";
if (IsStarknetNetwork(networkSlug)) return "Ready";
if (IsTronNetwork(networkSlug)) return "TronLink";
if (IsSolanaNetwork(networkSlug)) return "Solflare";
Expand All @@ -2041,6 +2064,9 @@

private async Task<string> SendTransactionViaWalletAsync(string networkSlug, string toAddress, string? data, string? amount)
{
if (IsAztecNetwork(networkSlug))
return await JS.InvokeAsync<string>("aztecUtils.sendTransaction", toAddress, data, amount, networkSlug);

if (IsStarknetNetwork(networkSlug))
return await JS.InvokeAsync<string>("starknetUtils.sendRawTransaction", toAddress, data, amount);

Expand Down
Loading
Loading