Skip to content

4.0.0

Choose a tag to compare

@github-actions github-actions released this 26 Aug 04:10
· 360 commits to main since this release
d2dd9a7

4.0.0 (diff)

Warning

This version is compatible with the [stellar/stellar-disbursement-platform-frontend] version 4.0.0.

Important

Potential Breaking Changes

We added wallet address uniqueness constraint that prevents the same wallet address from being assigned to multiple receivers. #750
Even though this shouldn't affect many users, it is still recommended to run this check using the pre-upgrade validation script at the end of the release notes.

Added

  • Added Bridge Integration API endpoints to the backend:
    • GET /bridge-integration to get the current integration status.
    • PATCH /bridge-integration to opt into the Bridge integration or create a virtual account.
    • #720
  • Added Bridge Helm chart configuration to the SDP charts #742
  • Add API keys management endpoints #677
  • Added a new endpoint to unregister a receiver wallet PATCH /receivers/wallets/:id/status. #675
  • Added a new authentication middleware to support API keys. #681
  • Added POST /receivers endpoint to create new receivers #687
  • Allow the serviceaccount to be set for the ap deployment in the helm chart #679
  • Add badges to the README.md file. #691
  • Add endpoint for the direct payments #693
  • Add type query parameter to GET /payments to filter direct/disbursement payments #694
  • Update wallet POST to allow accept new asset references #696
  • Update PATCH endpoint to extend update capabilities #697
  • Add supported_assets filter to GET /wallets endpoint #734
  • Add OTP attempt tracking and validation with maximum attempts limit and expiration checks for receiver wallet registration #773
  • Add asset filtering by trustline with balance information for GET /assets #791
  • Add AWS EKS CloudFormation deployment stacks #519

Changed

  • Update supported wallets for Pubnet and Testnet:
    • Removed Vibrant Assist wallets from pubnet and test configuration
    • Added Vesseo and Beans App on Pubnet
    • Added XLM as a supported asset for Decaf
    • #793
  • Optimize the Dockerfile to reduce the image size. #692
  • Refactor packages to reduce circular dependency issues #816, #817
  • Prevent unregistering user-managed wallets and wallets with in-progress payments #683

Fixed

  • Fix scheduler to only run jobs for provisioned and activated tenants, preventing execution for pending or deactivated tenants. #795
  • Display clear error message during reset password when token is expired. #783
  • Fix add_tests_users.sh script in main.sh for Alpine Linux. #738
  • Use sh instead of bash in e2e tests for better compatibility #736

Security and Dependencies

  • Update dependencies and address security alerts #755, #756
  • Pin @bitnami/readme-generator-for-helm version #731
  • Bump the minor-and-patch group across 1 directory with 6 updates. #690
  • Bump the minor-and-patch group across 1 directory with 10 updates #753, #769
  • Bump docker/build-push-action in the all-actions group #685, #801
  • Bump the all-docker group across 1 directory with 2 updates #709
  • Bump golang from 1.24.4-alpine to 1.24.6-alpine #760, #798
  • Bump github.com/go-chi/chi/v5 from 5.2.1 to 5.2.2 #719
  • Bump github.com/go-viper/mapstructure/v2 from 2.2.1 to 2.3.0 #752
  • Bump vite dependencies #654
  • Update stellar/go dependency to support Protocol 23 rollout #829

Pre-Upgrade Validation for Wallet Address Uniqueness

Version 4.0.0 introduces a constraint that prevents duplicate stellar addresses across receivers. You must run this validation script before upgrading to identify and resolve any existing duplicates.

Validation Script

-- Check for stellar address duplicates across all tenants
DO $$
DECLARE
    tenant_record RECORD;
    duplicate_count INTEGER;
    duplicate_record RECORD;
    schema_name TEXT;
    total_issues INTEGER := 0;
BEGIN
    RAISE NOTICE '=== Checking for stellar address duplicates across different receivers in all tenant schemas ===';
    RAISE NOTICE '';

    -- Loop through all active tenants
    FOR tenant_record IN 
        SELECT name, id, status 
        FROM admin.tenants 
        WHERE deleted_at IS NULL 
        AND status = 'TENANT_PROVISIONED'
        ORDER BY name
    LOOP
        schema_name := 'sdp_' || tenant_record.name;
        RAISE NOTICE 'Checking tenant: % (schema: %)', tenant_record.name, schema_name;
        
        -- Check if the schema exists and has receiver_wallets table
        IF EXISTS (
            SELECT 1 
            FROM information_schema.tables 
            WHERE table_schema = schema_name 
            AND table_name = 'receiver_wallets'
        ) THEN
            -- Count stellar addresses shared across multiple receivers in this tenant
            EXECUTE format('
                SELECT COUNT(*) 
                FROM (
                    SELECT stellar_address
                    FROM %I.receiver_wallets
                    WHERE stellar_address IS NOT NULL
                      AND trim(stellar_address) <> ''''
                    GROUP BY stellar_address
                    HAVING COUNT(DISTINCT receiver_id) > 1
                ) AS duplicates
            ', schema_name) INTO duplicate_count;
            
            IF duplicate_count > 0 THEN
                RAISE NOTICE '  ❌ FOUND % stellar address(es) shared across multiple receivers in %', duplicate_count, schema_name;
                total_issues := total_issues + duplicate_count;
                
                -- Show details of duplicates
                FOR duplicate_record IN 
                    EXECUTE format('
                        SELECT 
                            rw.stellar_address,
                            COUNT(DISTINCT rw.receiver_id) as receiver_count,
                            array_agg(DISTINCT rw.receiver_id) as receiver_ids,
                            array_agg(DISTINCT rw.id) as receiver_wallet_ids,
                            array_agg(DISTINCT r.email) as receiver_emails
                        FROM %I.receiver_wallets rw
                        JOIN %I.receivers r ON rw.receiver_id = r.id
                        WHERE rw.stellar_address IS NOT NULL
                          AND trim(rw.stellar_address) <> ''''
                        GROUP BY rw.stellar_address
                        HAVING COUNT(DISTINCT rw.receiver_id) > 1
                        ORDER BY rw.stellar_address
                    ', schema_name, schema_name)
                LOOP
                    RAISE NOTICE '    - Stellar Address: %', duplicate_record.stellar_address;
                    RAISE NOTICE '      Shared across % receivers: %', duplicate_record.receiver_count, duplicate_record.receiver_ids;
                    RAISE NOTICE '      Receiver emails: %', duplicate_record.receiver_emails;
                    RAISE NOTICE '      Receiver wallet IDs: %', duplicate_record.receiver_wallet_ids;
                    RAISE NOTICE '';
                END LOOP;
            ELSE
                RAISE NOTICE '  ✅ No stellar address duplicates found in %', schema_name;
            END IF;
        ELSE
            RAISE NOTICE '  ⚠️  Schema % or receiver_wallets table does not exist', schema_name;
        END IF;
    END LOOP;
    
    RAISE NOTICE '';
    RAISE NOTICE '=== SUMMARY ===';
    IF total_issues = 0 THEN
        RAISE NOTICE '✅ SUCCESS: No stellar address duplicates found. Safe to upgrade to v4.0.0.';
    ELSE
        RAISE NOTICE '❌ BLOCKING: Found % stellar address(es) shared across multiple receivers.', total_issues;
        RAISE NOTICE 'You must resolve these duplicates before upgrading to v4.0.0.';
    END IF;
END $$;

Remediation Steps

If duplicates are found, resolve them using this approach:

  1. Decide which of the receivers will get to keep the duplicate address
  2. Unregister duplicate receivers using this template:
-- Example: Unregister duplicate receiver wallet
-- Replace 'sdp_tenant_name' and receiver wallet ID with actual values
UPDATE sdp_tenant_name.receiver_wallets
SET status = 'READY',
    status_history = array_append(status_history, 
        sdp_tenant_name.create_receiver_wallet_status_history(NOW(), 'READY', 'unregistered duplicate')),
    stellar_address = NULL,
    stellar_memo = NULL,
    stellar_memo_type = NULL,
    invitation_sent_at = NULL,
    otp = NULL,
    otp_confirmed_at = NULL,
    otp_confirmed_with = NULL,
    otp_created_at = NULL,
    anchor_platform_transaction_id = NULL,
    anchor_platform_transaction_synced_at = NULL
WHERE id = 'duplicate-receiver-wallet-id';
  1. Re-run the validation script to confirm all duplicates are resolved
  2. Proceed with the upgrade once validation passes

Caution

The upgrade will fail if duplicate stellar addresses exist. Always run the validation script first.