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
17 changes: 17 additions & 0 deletions Backend (NestJS) – API Konversi Rupiah & Crypto
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Struktur Folder

backend-conversion/
├── src/
│ ├── auth/
│ ├── users/
│ ├── conversion/ # Modul utama untuk konversi Rupiah ↔ Crypto
│ ├── blockchain/
│ ├── config/
│ ├── main.ts
│ ├── app.module.ts
├── package.json
└── .env

Instalasi Dependensi

npm install @nestjs/common @nestjs/core @nestjs/config axios ethers web3
17 changes: 17 additions & 0 deletions Backend (NestJS) – API Pembayaran Merchant
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Struktur Folder:

backend-payment/
├── src/
│ ├── auth/
│ ├── users/
│ ├── payments/ # Modul utama untuk pembayaran merchant
│ ├── blockchain/
│ ├── config/
│ ├── main.ts
│ ├── app.module.ts
├── package.json
└── .env

Instalasi Dependensi

npm install @nestjs/common @nestjs/core @nestjs/config axios ethers web3
23 changes: 23 additions & 0 deletions Frontend (React + Next.js) – Checkout Merchant
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// pages/checkout.js
import { useState } from "react";
import { createPayment } from "../sdk/chainesia-sdk";

export default function Checkout() {
const [amount, setAmount] = useState("");
const [currency, setCurrency] = useState("idr");
const [paymentData, setPaymentData] = useState(null);

const handlePayment = async () => {
const response = await createPayment("MERCHANT_123", amount, currency);
setPaymentData(response);
};

return (
<div>
<h1>Checkout Merchant</h1>
<input type="number" value={amount} onChange={e => setAmount(e.target.value)} placeholder="Masukkan jumlah" />
<button onClick={handlePayment}>Bayar</button>
{paymentData && <p>Status: {paymentData.status}</p>}
</div>
);
}
20 changes: 20 additions & 0 deletions Implementasi Enkripsi AES-256
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// src/utils/encryption.ts
import * as crypto from 'crypto';

const algorithm = 'aes-256-cbc';
const key = Buffer.from(process.env.ENCRYPTION_KEY, 'hex');
const iv = Buffer.from(process.env.ENCRYPTION_IV, 'hex');

export function encryptData(data: string): string {
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(data, 'utf-8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}

export function decryptData(encrypted: string): string {
const decipher = crypto.createDecipheriv(algorithm, key, iv);
let decrypted = decipher.update(encrypted, 'hex', 'utf-8');
decrypted += decipher.final('utf-8');
return decrypted;
}
20 changes: 20 additions & 0 deletions Keamanan – Enkripsi & Proteksi Fraud
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// src/utils/encryption.ts
import * as crypto from 'crypto';

const algorithm = 'aes-256-cbc';
const key = Buffer.from(process.env.ENCRYPTION_KEY, 'hex');
const iv = Buffer.from(process.env.ENCRYPTION_IV, 'hex');

export function encryptData(data: string): string {
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(data, 'utf-8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}

export function decryptData(encrypted: string): string {
const decipher = crypto.createDecipheriv(algorithm, key, iv);
let decrypted = decipher.update(encrypted, 'hex', 'utf-8');
decrypted += decipher.final('utf-8');
return decrypted;
}
27 changes: 27 additions & 0 deletions Kode Backend
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// src/conversion/conversion.service.ts
import { Injectable } from '@nestjs/common';
import axios from 'axios';
import { ethers } from 'ethers';

@Injectable()
export class ConversionService {
private provider = new ethers.JsonRpcProvider(process.env.BLOCKCHAIN_RPC);
private wallet = new ethers.Wallet(process.env.PRIVATE_KEY, this.provider);

async getExchangeRate(from: string, to: string): Promise<number> {
const response = await axios.get(`https://api.coingecko.com/api/v3/simple/price?ids=${from}&vs_currencies=${to}`);
return response.data[from][to];
}

async convertAndSend(from: string, to: string, amount: number, recipient: string) {
const rate = await this.getExchangeRate(from, to);
const convertedAmount = amount * rate;

const tx = await this.wallet.sendTransaction({
to: recipient,
value: ethers.parseEther(convertedAmount.toString()),
});

return tx.wait();
}
}
39 changes: 39 additions & 0 deletions Kode Backend – API Pembayaran Merchant
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// src/payments/payments.service.ts
import { Injectable } from '@nestjs/common';
import axios from 'axios';
import { ethers } from 'ethers';

@Injectable()
export class PaymentsService {
private provider = new ethers.JsonRpcProvider(process.env.BLOCKCHAIN_RPC);
private wallet = new ethers.Wallet(process.env.PRIVATE_KEY, this.provider);

async getExchangeRate(from: string, to: string): Promise<number> {
const response = await axios.get(`https://api.coingecko.com/api/v3/simple/price?ids=${from}&vs_currencies=${to}`);
return response.data[from][to];
}

async createPayment(merchantId: string, amount: number, currency: string) {
const rate = await this.getExchangeRate(currency, 'idr');
const convertedAmount = amount * rate;

// Simpan ke database
return {
merchantId,
amount,
currency,
convertedAmount,
status: 'PENDING'
};
}

async processPayment(paymentId: string, sender: string) {
// Simpan transaksi ke blockchain
const tx = await this.wallet.sendTransaction({
to: sender,
value: ethers.parseEther("0.01"), // Nominal contoh
});

return tx.wait();
}
}
24 changes: 24 additions & 0 deletions Kode Frontend
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// pages/convert.js
import { useState } from "react";
import axios from "axios";

export default function ConvertPage() {
const [from, setFrom] = useState("idr");
const [to, setTo] = useState("ethereum");
const [amount, setAmount] = useState("");
const [convertedAmount, setConvertedAmount] = useState(null);

const handleConvert = async () => {
const response = await axios.post("/api/convert", { from, to, amount });
setConvertedAmount(response.data.convertedAmount);
};

return (
<div>
<h1>Konversi Rupiah ke Crypto</h1>
<input type="number" value={amount} onChange={e => setAmount(e.target.value)} placeholder="Masukkan jumlah" />
<button onClick={handleConvert}>Konversi</button>
{convertedAmount && <p>Hasil: {convertedAmount} {to.toUpperCase()}</p>}
</div>
);
}
19 changes: 19 additions & 0 deletions Proteksi Slippage (Fluktuasi Harga)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// src/conversion/conversion.service.ts
async convertAndSend(from: string, to: string, amount: number, recipient: string) {
const rate = await this.getExchangeRate(from, to);
const convertedAmount = amount * rate;

// Proteksi jika harga berubah lebih dari 1%
const maxSlippage = 0.01; // 1%
const currentRate = await this.getExchangeRate(from, to);
if (Math.abs((currentRate - rate) / rate) > maxSlippage) {
throw new Error("Harga berubah terlalu cepat, transaksi dibatalkan.");
}

const tx = await this.wallet.sendTransaction({
to: recipient,
value: ethers.parseEther(convertedAmount.toString()),
});

return tx.wait();
}
Loading